You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by th...@apache.org on 2020/09/14 16:38:26 UTC

[lucene-solr] 08/39: LUCENE-9435: Clean up ant compatability remnants in Gradle build

This is an automated email from the ASF dual-hosted git repository.

thelabdude pushed a commit to branch reference_impl_gradle_updates
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git

commit 969c8ec597e455f1e007e0c776ff5d9959da44f2
Author: Dawid Weiss <da...@carrotsearch.com>
AuthorDate: Sun Aug 30 14:01:04 2020 +0200

    LUCENE-9435: Clean up ant compatability remnants in Gradle build
    
    * Removing ant-only unused tasks.
    * Correct message in TestVersion.java
    * Remove unused file.
    * Removing forbidden API rules for ant.
    * Remove 'resolve' emulation.
    * Move ecj-lint to task-definition-relative folder.
    * Remove 'packaging' specification. It'll have to wait until proper new packaging is implemented for Solr distribution.
    * Move render-javadoc tasks's files to task-relative location.
    * Moved security manager policies and default JDK logging file to gradle's task relative locations.
    * Removing obsolete ant tools. Moving check source patterns under gradle's folder.
    * Correct paths.
    * Correct property name in task selector.
---
 build.gradle                                       |   2 -
 .../ant-compat/forbidden-api-rules-in-sync.gradle  |  54 --
 gradle/ant-compat/jar-checks.gradle                |  26 -
 gradle/ant-compat/solr-forbidden-apis.gradle       |   2 +-
 gradle/documentation/render-javadoc.gradle         |  15 +-
 .../render-javadoc}/java11/package-list            |   0
 .../render-javadoc}/junit/package-list             |   0
 .../render-javadoc}/prettify/inject-javadocs.js    |   0
 .../render-javadoc}/prettify/prettify.css          |   0
 .../render-javadoc}/prettify/prettify.js           |   0
 .../render-javadoc}/table_padding.css              |   0
 gradle/testing/defaults-tests.gradle               |   2 +-
 .../testing/defaults-tests}/logging.properties     |   0
 .../testing/policies}/replicator-tests.policy      |   0
 .../testing/policies}/tests.policy                 |   0
 gradle/testing/randomization.gradle                |   4 +-
 gradle/validation/ecj-lint.gradle                  |   2 +-
 .../validation/ecj-lint}/ecj.javadocs.prefs        |   0
 gradle/validation/forbidden-apis.gradle            |   2 +-
 gradle/validation/validate-source-patterns.gradle  |   4 +-
 .../check-source-patterns.groovy                   |   0
 .../test/org/apache/lucene/util/TestVersion.java   |   2 +-
 lucene/tools/build.xml                             |  64 --
 lucene/tools/custom-tasks.xml                      | 149 ----
 lucene/tools/forbiddenApis/base.txt                |  64 --
 lucene/tools/forbiddenApis/lucene.txt              |  49 --
 lucene/tools/forbiddenApis/servlet-api.txt         |  43 -
 lucene/tools/forbiddenApis/solr.txt                |  61 --
 lucene/tools/forbiddenApis/tests.txt               |  29 -
 lucene/tools/ivy.xml                               |  29 -
 lucene/tools/junit4/cached-timehints.txt           |   0
 lucene/tools/src/groovy/check-working-copy.groovy  |  61 --
 .../src/groovy/install-markdown-filter.groovy      |  61 --
 lucene/tools/src/groovy/run-beaster.groovy         | 121 ---
 lucene/tools/src/groovy/run-maven-build.groovy     |  50 --
 lucene/tools/src/java/lucene-solr.antlib.xml       |  27 -
 .../dependencies/GetMavenDependenciesTask.java     | 920 ---------------------
 .../dependencies/InterpolatedProperties.java       | 162 ----
 .../lucene/validation/LibVersionsCheckTask.java    | 903 --------------------
 .../apache/lucene/validation/LicenseCheckTask.java | 352 --------
 .../org/apache/lucene/validation/LicenseType.java  |  75 --
 .../lucene/validation/ivyde/IvyNodeElement.java    | 178 ----
 .../validation/ivyde/IvyNodeElementAdapter.java    | 135 ---
 solr/contrib/prometheus-exporter/build.gradle      |   8 -
 44 files changed, 18 insertions(+), 3638 deletions(-)

diff --git a/build.gradle b/build.gradle
index ec5fed0..4c8209a 100644
--- a/build.gradle
+++ b/build.gradle
@@ -163,12 +163,10 @@ apply from: file('gradle/help.gradle')
 // of potential problems with the build conventions, dependencies, etc.
 apply from: file('gradle/ant-compat/force-versions.gradle')
 apply from: file('gradle/ant-compat/misc.gradle')
-apply from: file('gradle/ant-compat/resolve.gradle')
 apply from: file('gradle/ant-compat/post-jar.gradle')
 apply from: file('gradle/ant-compat/test-classes-cross-deps.gradle')
 apply from: file('gradle/ant-compat/artifact-naming.gradle')
 apply from: file('gradle/ant-compat/solr-forbidden-apis.gradle')
-apply from: file('gradle/ant-compat/forbidden-api-rules-in-sync.gradle')
 
 apply from: file('gradle/documentation/documentation.gradle')
 apply from: file('gradle/documentation/changes-to-html.gradle')
diff --git a/gradle/ant-compat/forbidden-api-rules-in-sync.gradle b/gradle/ant-compat/forbidden-api-rules-in-sync.gradle
deleted file mode 100644
index c36847f..0000000
--- a/gradle/ant-compat/forbidden-api-rules-in-sync.gradle
+++ /dev/null
@@ -1,54 +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.
- */
-
-
-// Just make sure the forbidden API rules are in sync between gradle and ant versions until
-// we get rid of ant build.
-
-def linesOf(FileTree ftree) {
-  return ftree.collectMany { path ->
-    path.readLines("UTF-8")
-      .collect { line -> line.trim() }
-      .findAll { line -> !line.startsWith("#") }
-      .unique()
-      .collect { line -> [path: path, line: line] }
-  }.groupBy { e -> e.line }
-}
-
-configure(rootProject) {
-  task verifyForbiddenApiRulesInSync() {
-    doFirst {
-      // Read all rules line by line from ant, gradle, remove comments, uniq.
-      // Rule sets should be identical.
-      def gradleRules = linesOf(fileTree("gradle/validation/forbidden-apis", { include "**/*.txt" }))
-      def antRules = linesOf(project(":lucene").fileTree("tools/forbiddenApis", { include "**/*.txt" }))
-
-      def antOnlyLines = antRules.keySet() - gradleRules.keySet()
-      def gradleOnlyLines = gradleRules.keySet() - antRules.keySet()
-
-      if (!gradleOnlyLines.isEmpty() || !antOnlyLines.isEmpty()) {
-        project.logger.log(LogLevel.ERROR, "The following rules don't have counterparts:\n" +
-          (gradleRules.findAll { gradleOnlyLines.contains(it.key) } + antRules.findAll { antOnlyLines.contains(it.key)})
-            .collectMany { it.value }
-            .join("\n"))
-        throw new GradleException("Forbidden APIs rules out of sync.")
-      }
-    }
-  }
-
-  check.dependsOn verifyForbiddenApiRulesInSync
-}
diff --git a/gradle/ant-compat/jar-checks.gradle b/gradle/ant-compat/jar-checks.gradle
deleted file mode 100644
index a93a002..0000000
--- a/gradle/ant-compat/jar-checks.gradle
+++ /dev/null
@@ -1,26 +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.
- */
-
-
-// This file is not included but is kept in ant-compat so that cleanup can be done later
-
-// Remove special handling of dependency checksum validation/ collection for Solr where
-// transitive Lucene dependencies are sucked in to licenses/ folder. We can just copy
-// Lucene licenses as a whole (they're joint projects after all).
-//
-// the hack is in 'jar-checks.gradle' under:
-// def isSolr = project.path.startsWith(":solr")
diff --git a/gradle/ant-compat/solr-forbidden-apis.gradle b/gradle/ant-compat/solr-forbidden-apis.gradle
index e55c745..bb4dc60 100644
--- a/gradle/ant-compat/solr-forbidden-apis.gradle
+++ b/gradle/ant-compat/solr-forbidden-apis.gradle
@@ -19,7 +19,7 @@
 // Why does solr exclude these from forbidden API checks?
 
 configure(project(":solr:core")) {
-  configure([forbiddenApisMain, forbiddenApisTest]) {
+  tasks.matching { it.name == "forbiddenApisMain" || it.name == "forbiddenApisTest" }.all {
     exclude "org/apache/solr/internal/**"
     exclude "org/apache/hadoop/**"
   }
diff --git a/gradle/documentation/render-javadoc.gradle b/gradle/documentation/render-javadoc.gradle
index 27d282b..a7a76ef 100644
--- a/gradle/documentation/render-javadoc.gradle
+++ b/gradle/documentation/render-javadoc.gradle
@@ -65,8 +65,9 @@ allprojects {
 
 // Set up titles and link up some offline docs for all documentation
 // (they may be unused but this doesn't do any harm).
-def javaJavadocPackages = project.project(':lucene').file('tools/javadoc/java11/')
-def junitJavadocPackages = project.project(':lucene').file('tools/javadoc/junit/')
+def taskResources = "${rootProject.projectDir}/gradle/documentation/render-javadoc"
+def javaJavadocPackages = rootProject.file("${taskResources}/java11/")
+def junitJavadocPackages = rootProject.file("${taskResources}/junit/")
 allprojects {
   project.tasks.withType(RenderJavadocTask) {
     title = "${project.path.startsWith(':lucene') ? 'Lucene' : 'Solr'} ${project.version} ${project.name} API"
@@ -305,15 +306,19 @@ class RenderJavadocTask extends DefaultTask {
       throw new GradleException("Javadoc generation failed for ${project.path},\n  Options file at: ${optionsFile}\n  Command output at: ${outputFile}", cause)
     }
 
+    def taskResources = "${project.rootDir}/gradle/documentation/render-javadoc"
+
     // append some special table css, prettify css
     ant.concat(destfile: "${outputDir}/stylesheet.css", append: "true", fixlastline: "true", encoding: "UTF-8") {
-      filelist(dir: project.project(":lucene").file("tools/javadoc"), files: "table_padding.css")
-      filelist(dir: project.project(":lucene").file("tools/prettify"), files: "prettify.css")
+      filelist(dir: taskResources, files: "table_padding.css")
+      filelist(dir: project.file("${taskResources}/prettify"), files: "prettify.css")
     }
+
     // append prettify to scripts
     ant.concat(destfile: "${outputDir}/script.js", append: "true", fixlastline: "true", encoding: "UTF-8") {
-      filelist(dir: project.project(':lucene').file("tools/prettify"), files: "prettify.js inject-javadocs.js")
+      filelist(dir: project.file("${taskResources}/prettify"), files: "prettify.js inject-javadocs.js")
     }
+
     ant.fixcrlf(srcdir: outputDir, includes: "stylesheet.css script.js", eol: "lf", fixlast: "true", encoding: "UTF-8")
   }
 }
diff --git a/lucene/tools/javadoc/java11/package-list b/gradle/documentation/render-javadoc/java11/package-list
similarity index 100%
rename from lucene/tools/javadoc/java11/package-list
rename to gradle/documentation/render-javadoc/java11/package-list
diff --git a/lucene/tools/javadoc/junit/package-list b/gradle/documentation/render-javadoc/junit/package-list
similarity index 100%
rename from lucene/tools/javadoc/junit/package-list
rename to gradle/documentation/render-javadoc/junit/package-list
diff --git a/lucene/tools/prettify/inject-javadocs.js b/gradle/documentation/render-javadoc/prettify/inject-javadocs.js
similarity index 100%
rename from lucene/tools/prettify/inject-javadocs.js
rename to gradle/documentation/render-javadoc/prettify/inject-javadocs.js
diff --git a/lucene/tools/prettify/prettify.css b/gradle/documentation/render-javadoc/prettify/prettify.css
similarity index 100%
rename from lucene/tools/prettify/prettify.css
rename to gradle/documentation/render-javadoc/prettify/prettify.css
diff --git a/lucene/tools/prettify/prettify.js b/gradle/documentation/render-javadoc/prettify/prettify.js
similarity index 100%
rename from lucene/tools/prettify/prettify.js
rename to gradle/documentation/render-javadoc/prettify/prettify.js
diff --git a/lucene/tools/javadoc/table_padding.css b/gradle/documentation/render-javadoc/table_padding.css
similarity index 100%
rename from lucene/tools/javadoc/table_padding.css
rename to gradle/documentation/render-javadoc/table_padding.css
diff --git a/gradle/testing/defaults-tests.gradle b/gradle/testing/defaults-tests.gradle
index 9bca17b..c4316d5 100644
--- a/gradle/testing/defaults-tests.gradle
+++ b/gradle/testing/defaults-tests.gradle
@@ -72,7 +72,7 @@ allprojects {
 
       jvmArgs Commandline.translateCommandline(propertyOrDefault("tests.jvmargs", "-XX:TieredStopAtLevel=1 -XX:+UseParallelGC -XX:-UseBiasedLocking -DconfigurationFile=log4j2.xml -Dorg.apache.xml.dtm.DTMManager=org.apache.xml.dtm.ref.DTMManagerDefault"));
 
-      systemProperty 'java.util.logging.config.file', file("${commonDir}/tools/junit4/logging.properties")
+      systemProperty 'java.util.logging.config.file', rootProject.file("gradle/testing/defaults-tests/logging.properties")
       systemProperty 'java.awt.headless', 'true'
       systemProperty 'jdk.map.althashing.threshold', '0'
 
diff --git a/lucene/tools/junit4/logging.properties b/gradle/testing/defaults-tests/logging.properties
similarity index 100%
rename from lucene/tools/junit4/logging.properties
rename to gradle/testing/defaults-tests/logging.properties
diff --git a/lucene/tools/junit4/replicator-tests.policy b/gradle/testing/policies/replicator-tests.policy
similarity index 100%
rename from lucene/tools/junit4/replicator-tests.policy
rename to gradle/testing/policies/replicator-tests.policy
diff --git a/lucene/tools/junit4/tests.policy b/gradle/testing/policies/tests.policy
similarity index 100%
rename from lucene/tools/junit4/tests.policy
rename to gradle/testing/policies/tests.policy
diff --git a/gradle/testing/randomization.gradle b/gradle/testing/randomization.gradle
index f1d57d0..eb539c7 100644
--- a/gradle/testing/randomization.gradle
+++ b/gradle/testing/randomization.gradle
@@ -177,10 +177,10 @@ allprojects {
         if (Boolean.parseBoolean(testOptionsResolved["tests.useSecurityManager"])) {
           if (project.path == ":lucene:replicator") {
             systemProperty 'java.security.manager', "org.apache.lucene.util.TestSecurityManager"
-            systemProperty 'java.security.policy', rootProject.file("lucene/tools/junit4/replicator-tests.policy")
+            systemProperty 'java.security.policy', rootProject.file("gradle/testing/policies/replicator-tests.policy")
           } else if (project.path.startsWith(":lucene")) {
             systemProperty 'java.security.manager', "org.apache.lucene.util.TestSecurityManager"
-            systemProperty 'java.security.policy', rootProject.file("lucene/tools/junit4/tests.policy")
+            systemProperty 'java.security.policy', rootProject.file("gradle/testing/policies/tests.policy")
           } else {
             systemProperty 'common-solr.dir', commonSolrDir
             systemProperty 'java.security.manager', "org.apache.lucene.util.TestSecurityManager"
diff --git a/gradle/validation/ecj-lint.gradle b/gradle/validation/ecj-lint.gradle
index 5ae13c1..56bbd8d 100644
--- a/gradle/validation/ecj-lint.gradle
+++ b/gradle/validation/ecj-lint.gradle
@@ -69,7 +69,7 @@ allprojects {
         args += [ "-proc:none" ]
         args += [ "-nowarn" ]
         args += [ "-enableJavadoc" ]
-        args += [ "-properties", project(":lucene").file("tools/javadoc/ecj.javadocs.prefs").absolutePath ]
+        args += [ "-properties", rootProject.file("gradle/validation/ecj-lint/ecj.javadocs.prefs").absolutePath ]
 
         doFirst {
           tmpDst.mkdirs()
diff --git a/lucene/tools/javadoc/ecj.javadocs.prefs b/gradle/validation/ecj-lint/ecj.javadocs.prefs
similarity index 100%
rename from lucene/tools/javadoc/ecj.javadocs.prefs
rename to gradle/validation/ecj-lint/ecj.javadocs.prefs
diff --git a/gradle/validation/forbidden-apis.gradle b/gradle/validation/forbidden-apis.gradle
index 33c1d68..8fe5199 100644
--- a/gradle/validation/forbidden-apis.gradle
+++ b/gradle/validation/forbidden-apis.gradle
@@ -1,4 +1,4 @@
-/*
+  /*
  * 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.
diff --git a/gradle/validation/validate-source-patterns.gradle b/gradle/validation/validate-source-patterns.gradle
index 53630ed..ce27e2d 100644
--- a/gradle/validation/validate-source-patterns.gradle
+++ b/gradle/validation/validate-source-patterns.gradle
@@ -15,8 +15,6 @@
  * limitations under the License.
  */
 
-
-// Equivalent of ant's "validate-source-patterns".
 // This should be eventually rewritten in plain gradle. For now, delegate to
 // the ant/groovy script we already have.
 
@@ -37,7 +35,7 @@ configure(rootProject) {
           classname: "org.codehaus.groovy.ant.Groovy",
           classpath: configurations.checkSourceDeps.asPath)
 
-      ant.groovy(src: project(":lucene").file("tools/src/groovy/check-source-patterns.groovy"))
+      ant.groovy(src: rootProject.file("gradle/validation/validate-source-patterns/check-source-patterns.groovy"))
     }
   }
 }
\ No newline at end of file
diff --git a/lucene/tools/src/groovy/check-source-patterns.groovy b/gradle/validation/validate-source-patterns/check-source-patterns.groovy
similarity index 100%
rename from lucene/tools/src/groovy/check-source-patterns.groovy
rename to gradle/validation/validate-source-patterns/check-source-patterns.groovy
diff --git a/lucene/core/src/test/org/apache/lucene/util/TestVersion.java b/lucene/core/src/test/org/apache/lucene/util/TestVersion.java
index e19c615..36cb1a5 100644
--- a/lucene/core/src/test/org/apache/lucene/util/TestVersion.java
+++ b/lucene/core/src/test/org/apache/lucene/util/TestVersion.java
@@ -192,7 +192,7 @@ public class TestVersion extends LuceneTestCase {
     String commonBuildVersion = System.getProperty("tests.LUCENE_VERSION");
     assumeTrue("Null 'tests.LUCENE_VERSION' test property. You should run the tests with the official Lucene build file",
         commonBuildVersion != null);
-    assertEquals("Version.LATEST does not match the one given in common-build.xml",
+    assertEquals("Version.LATEST does not match the one given in tests.LUCENE_VERSION property",
         Version.LATEST.toString(), commonBuildVersion);
   }
 
diff --git a/lucene/tools/build.xml b/lucene/tools/build.xml
deleted file mode 100644
index b245dce..0000000
--- a/lucene/tools/build.xml
+++ /dev/null
@@ -1,64 +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="tools" default="default">
-  <description>Lucene Tools</description>
-
-  <property name="build.dir" location="../build/tools"/>
-  
-  <property name="rat.additional-includes" value="forbiddenApis/**,prettify/**"/>
-
-  <import file="../common-build.xml"/>
-
-  <path id="classpath">
-    <!-- TODO: we need this for forbidden-apis to be happy, because it does not support "includeantruntime": -->
-    <fileset dir="lib"/>
-  </path>
-
-  <path id="test.classpath"/>
-
-  <!-- redefine the test compilation, -test and -check-totals, so these are just no-ops -->
-  <target name="compile-test"/>
-  <target name="-test"/>
-  <target name="-check-totals"/>
-  
-  <!-- redefine the forbidden apis to be no-ops -->
-  <target name="-check-forbidden-tests"/>
-  <target name="-check-forbidden-sysout"/>
-
-  <!-- disable clover -->
-  <target name="-clover.setup" if="run.clover"/>
-
-  <!--  
-      Specialize compile-core to not depend on clover, to exclude a 
-      classpath reference when compiling, and to not attempt to copy
-      non-existent resource files to the build output directory.
-   -->
-  <target name="compile-core" depends="init" description="Compiles tools classes.">
-    <compile srcdir="${src.dir}" destdir="${build.dir}/classes/java" includeantruntime="true">
-      <classpath refid="classpath"/>
-    </compile>
-    <copy todir="${build.dir}/classes/java">
-      <fileset dir="${src.dir}" excludes="**/*.java" />
-    </copy>
-  </target>
-
-  <target name="javadocs"/> <!-- to make common-build.xml happy -->
-  <target name="pitest"/> <!-- to make common-build.xml happy -->
-</project>
diff --git a/lucene/tools/custom-tasks.xml b/lucene/tools/custom-tasks.xml
deleted file mode 100644
index 4b5c3ea..0000000
--- a/lucene/tools/custom-tasks.xml
+++ /dev/null
@@ -1,149 +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.
--->
-<project name="custom-tasks">
-  <description>
-    This file is designed for importing into a main build file, and not intended
-    for standalone use.
-  </description>
-
-  <target name="load-custom-tasks" unless="custom-tasks.loaded">
-    <dirname file="${ant.file.custom-tasks}" property="custom-tasks.dir"/>
-    <taskdef resource="lucene-solr.antlib.xml">
-      <classpath>
-        <pathelement location="${custom-tasks.dir}/../build/tools/classes/java" />
-      </classpath>
-    </taskdef>
-    <property name="custom-tasks.loaded" value="true"/>
-  </target>
-
-  <filtermapper id="license-mapper-defaults">
-    <!-- Normalize input paths. -->
-    <replacestring from="\" to="/" />
-    <replaceregex pattern="\.jar$" replace="" flags="gi" />
-    
-    <!-- Some typical snapshot/minimalized JAR suffixes. -->
-    <replaceregex pattern="-min$" replace="" flags="gi" />
-    <replaceregex pattern="SNAPSHOT" replace="" flags="gi" />
-
-    <!-- Typical version patterns. -->
-    <replaceregex pattern="\.rc[0-9]+" replace="" flags="gi" />
-    <replaceregex pattern="(?&lt;!log4j)\-(r)?([0-9\-\_\.])+(([a-zA-Z]+)([0-9\-\.])*)?" replace="" flags="gi" />
-    
-    <replaceregex pattern="[-]tests$" replace="-tests" flags="gi" />
-
-    <!-- git hashcode pattern: it's always 40 chars right? -->
-    <replaceregex pattern="\-[a-z0-9]{40,40}$" replace="" flags="gi" />
-  </filtermapper>
-
-  <macrodef name="license-check-macro">
-    <attribute name="dir" />
-    <attribute name="licensedir" />
-    <element name="additional-excludes" optional="true" />
-    <element name="additional-filters"  optional="true" />
-    <sequential>
-      <!-- LICENSE and NOTICE verification macro. -->
-      <echo>License check under: @{dir}</echo>
-      <licenses licenseDirectory="@{licensedir}" skipChecksum="${skipChecksum}" skipRegexChecksum="${skipRegexChecksum}" skipSnapshotsChecksum="${skipSnapshotsChecksum}">
-        <fileset dir="@{dir}">
-          <include name="**/*.jar" />
-          <!-- Speed up scanning a bit. -->
-          <exclude name="**/.git/**" />
-          <exclude name="**/.svn/**" />
-          <exclude name="**/bin/**" />
-          <exclude name="**/build/**" />
-          <exclude name="**/dist/**" />
-          <exclude name="**/src/**" />
-          <additional-excludes />
-        </fileset>
-
-        <licenseMapper>
-          <chainedmapper>
-            <filtermapper refid="license-mapper-defaults"/>
-            <filtermapper>
-              <!-- Non-typical version patterns. -->
-              <additional-filters />
-            </filtermapper>
-          </chainedmapper>
-        </licenseMapper>
-      </licenses>
-    </sequential>
-  </macrodef>
-
-  <macrodef name="lib-versions-check-macro">
-    <attribute name="dir"/>
-    <attribute name="centralized.versions.file"/>
-    <attribute name="top.level.ivy.settings.file"/>
-    <attribute name="ivy.resolution-cache.dir"/>
-    <attribute name="ivy.lock-strategy"/>
-    <attribute name="common.build.dir"/>
-    <attribute name="ignore.conflicts.file"/>
-    <sequential>
-      <!-- 
-        Verify that the '/org/name' keys in ivy-versions.properties are sorted
-        lexically and are neither duplicates nor orphans, and that all
-         dependencies in all ivy.xml files use rev="${/org/name}" format.
-        -->
-      <echo>Lib versions check under: @{dir}</echo>
-      <libversions centralizedVersionsFile="@{centralized.versions.file}"
-                   topLevelIvySettingsFile="@{top.level.ivy.settings.file}"
-                   ivyResolutionCacheDir="@{ivy.resolution-cache.dir}"
-                   ivyLockStrategy="@{ivy.lock-strategy}"
-                   commonBuildDir="@{common.build.dir}"
-                   ignoreConflictsFile="@{ignore.conflicts.file}">
-        <fileset dir="@{dir}">
-          <include name="**/ivy.xml" />
-          <!-- Speed up scanning a bit. -->
-          <exclude name="**/.git/**" />
-          <exclude name="**/.svn/**" />
-          <exclude name="**/bin/**" />
-          <exclude name="**/build/**" />
-          <exclude name="**/dist/**" />
-          <exclude name="**/src/**" />
-        </fileset>
-      </libversions>
-    </sequential>
-  </macrodef>
-
-  <macrodef name="get-maven-dependencies-macro">
-    <attribute name="dir"/>
-    <attribute name="centralized.versions.file"/>
-    <attribute name="module.dependencies.properties.file"/>
-    <attribute name="maven.dependencies.filters.file"/>
-    <sequential>
-      <echo>Get maven dependencies called under: @{dir}</echo>
-      <mvndeps centralizedVersionsFile="@{centralized.versions.file}"
-               moduleDependenciesPropertiesFile="@{module.dependencies.properties.file}"
-               mavenDependenciesFiltersFile="@{maven.dependencies.filters.file}">
-        <fileset dir="@{dir}">
-          <include name="**/ivy.xml" />
-          <!-- Speed up scanning a bit. -->
-          <exclude name="**/.git/**" />
-          <exclude name="**/.svn/**" />
-          <exclude name="**/bin/**" />
-          <exclude name="**/build/**" />
-          <exclude name="**/dist/**" />
-          <exclude name="**/src/**" />
-          <exclude name="**/maven-build/**" />
-          <exclude name="**/idea-build/**" />
-          <exclude name="**/dev-tools/**" />
-        </fileset>
-      </mvndeps>
-    </sequential>
-  </macrodef>
-</project>
diff --git a/lucene/tools/forbiddenApis/base.txt b/lucene/tools/forbiddenApis/base.txt
deleted file mode 100644
index 6ff080b..0000000
--- a/lucene/tools/forbiddenApis/base.txt
+++ /dev/null
@@ -1,64 +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.
-
-@defaultMessage Spawns threads with vague names; use a custom thread factory (Lucene's NamedThreadFactory, Solr's SolrNamedThreadFactory) and name threads so that you can tell (by its name) which executor it is associated with
-java.util.concurrent.Executors#newFixedThreadPool(int)
-java.util.concurrent.Executors#newSingleThreadExecutor()
-java.util.concurrent.Executors#newCachedThreadPool()
-java.util.concurrent.Executors#newSingleThreadScheduledExecutor()
-java.util.concurrent.Executors#newScheduledThreadPool(int)
-java.util.concurrent.Executors#defaultThreadFactory()
-java.util.concurrent.Executors#privilegedThreadFactory()
-
-@defaultMessage Properties files should be read/written with Reader/Writer, using UTF-8 charset. This allows reading older files with unicode escapes, too.
-java.util.Properties#load(java.io.InputStream)
-java.util.Properties#save(java.io.OutputStream,java.lang.String)
-java.util.Properties#store(java.io.OutputStream,java.lang.String)
-
-@defaultMessage The context classloader should never be used for resource lookups, unless there is a 3rd party library that needs it. Always pass a classloader down as method parameters.
-java.lang.Thread#getContextClassLoader()
-java.lang.Thread#setContextClassLoader(java.lang.ClassLoader)
-
-java.lang.Character#codePointBefore(char[],int) @ Implicit start offset is error-prone when the char[] is a buffer and the first chars are random chars
-java.lang.Character#codePointAt(char[],int) @ Implicit end offset is error-prone when the char[] is a buffer and the last chars are random chars
-
-java.io.File#delete() @ use Files.delete for real exception, IOUtils.deleteFilesIgnoringExceptions if you dont care
-
-java.util.Collections#shuffle(java.util.List) @ Use shuffle(List, Random) instead so that it can be reproduced
-
-java.util.Locale#forLanguageTag(java.lang.String) @ use new Locale.Builder().setLanguageTag(...).build() which has error handling
-java.util.Locale#toString() @ use Locale#toLanguageTag() for a standardized BCP47 locale name
-
-@defaultMessage Constructors for wrapper classes of Java primitives should be avoided in favor of the public static methods available or autoboxing
-java.lang.Integer#<init>(int)
-java.lang.Integer#<init>(java.lang.String)
-java.lang.Byte#<init>(byte)
-java.lang.Byte#<init>(java.lang.String)
-java.lang.Short#<init>(short)
-java.lang.Short#<init>(java.lang.String)
-java.lang.Long#<init>(long)
-java.lang.Long#<init>(java.lang.String)
-java.lang.Boolean#<init>(boolean)
-java.lang.Boolean#<init>(java.lang.String)
-java.lang.Character#<init>(char)
-java.lang.Float#<init>(float)
-java.lang.Float#<init>(double)
-java.lang.Float#<init>(java.lang.String)
-java.lang.Double#<init>(double)
-java.lang.Double#<init>(java.lang.String)
-
-@defaultMessage Java deserialization is unsafe when the data is untrusted. The java developer is powerless: no checks or casts help, exploitation can happen in places such as clinit or finalize!
-java.io.ObjectInputStream
-java.io.ObjectOutputStream
diff --git a/lucene/tools/forbiddenApis/lucene.txt b/lucene/tools/forbiddenApis/lucene.txt
deleted file mode 100644
index 0cc4edd..0000000
--- a/lucene/tools/forbiddenApis/lucene.txt
+++ /dev/null
@@ -1,49 +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.
-
-@defaultMessage Use NIO.2 instead
-java.io.File
-java.io.FileInputStream
-java.io.FileOutputStream
-java.io.PrintStream#<init>(java.lang.String,java.lang.String)
-java.io.PrintWriter#<init>(java.lang.String,java.lang.String)
-java.util.Formatter#<init>(java.lang.String,java.lang.String,java.util.Locale)
-java.io.RandomAccessFile
-java.nio.file.Path#toFile()
-java.util.jar.JarFile
-java.util.zip.ZipFile
-@defaultMessage Prefer using ArrayUtil as Arrays#copyOfRange fills zeros for bad bounds
-java.util.Arrays#copyOfRange(byte[],int,int)
-java.util.Arrays#copyOfRange(char[],int,int)
-java.util.Arrays#copyOfRange(short[],int,int)
-java.util.Arrays#copyOfRange(int[],int,int)
-java.util.Arrays#copyOfRange(long[],int,int)
-java.util.Arrays#copyOfRange(float[],int,int)
-java.util.Arrays#copyOfRange(double[],int,int)
-java.util.Arrays#copyOfRange(boolean[],int,int)
-java.util.Arrays#copyOfRange(java.lang.Object[],int,int)
-java.util.Arrays#copyOfRange(java.lang.Object[],int,int,java.lang.Class)
-
-@defaultMessage Prefer using ArrayUtil as Arrays#copyOf fills zeros for bad bounds
-java.util.Arrays#copyOf(byte[],int)
-java.util.Arrays#copyOf(char[],int)
-java.util.Arrays#copyOf(short[],int)
-java.util.Arrays#copyOf(int[],int)
-java.util.Arrays#copyOf(long[],int)
-java.util.Arrays#copyOf(float[],int)
-java.util.Arrays#copyOf(double[],int)
-java.util.Arrays#copyOf(boolean[],int)
-java.util.Arrays#copyOf(java.lang.Object[],int)
-java.util.Arrays#copyOf(java.lang.Object[],int,java.lang.Class)
diff --git a/lucene/tools/forbiddenApis/servlet-api.txt b/lucene/tools/forbiddenApis/servlet-api.txt
deleted file mode 100644
index dc82e8f..0000000
--- a/lucene/tools/forbiddenApis/servlet-api.txt
+++ /dev/null
@@ -1,43 +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.
-
-@defaultMessage Servlet API method is parsing request parameters without using the correct encoding if no extra configuration is given in the servlet container
-
-javax.servlet.ServletRequest#getParameter(java.lang.String) 
-javax.servlet.ServletRequest#getParameterMap() 
-javax.servlet.ServletRequest#getParameterNames() 
-javax.servlet.ServletRequest#getParameterValues(java.lang.String) 
-
-javax.servlet.http.HttpServletRequest#getSession() @ Servlet API getter has side effect of creating sessions
-
-@defaultMessage Servlet API method is broken and slow in some environments (e.g., Jetty's UTF-8 readers)
-
-javax.servlet.ServletRequest#getReader()
-javax.servlet.ServletResponse#getWriter()
-javax.servlet.ServletInputStream#readLine(byte[],int,int) 
-javax.servlet.ServletOutputStream#print(boolean)
-javax.servlet.ServletOutputStream#print(char)
-javax.servlet.ServletOutputStream#print(double)
-javax.servlet.ServletOutputStream#print(float)
-javax.servlet.ServletOutputStream#print(int)
-javax.servlet.ServletOutputStream#print(long)
-javax.servlet.ServletOutputStream#print(java.lang.String)
-javax.servlet.ServletOutputStream#println(boolean)
-javax.servlet.ServletOutputStream#println(char)
-javax.servlet.ServletOutputStream#println(double)
-javax.servlet.ServletOutputStream#println(float)
-javax.servlet.ServletOutputStream#println(int)
-javax.servlet.ServletOutputStream#println(long)
-javax.servlet.ServletOutputStream#println(java.lang.String)
diff --git a/lucene/tools/forbiddenApis/solr.txt b/lucene/tools/forbiddenApis/solr.txt
deleted file mode 100644
index bb177be..0000000
--- a/lucene/tools/forbiddenApis/solr.txt
+++ /dev/null
@@ -1,61 +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.
-
-@defaultMessage Spawns threads without MDC logging context; use ExecutorUtil.newMDCAwareFixedThreadPool instead
-java.util.concurrent.Executors#newFixedThreadPool(int,java.util.concurrent.ThreadFactory)
-
-@defaultMessage Spawns threads without MDC logging context; use ExecutorUtil.newMDCAwareSingleThreadExecutor instead
-java.util.concurrent.Executors#newSingleThreadExecutor(java.util.concurrent.ThreadFactory)
-
-@defaultMessage Spawns threads without MDC logging context; use ExecutorUtil.newMDCAwareCachedThreadPool instead
-java.util.concurrent.Executors#newCachedThreadPool(java.util.concurrent.ThreadFactory)
-
-@defaultMessage Use ExecutorUtil.MDCAwareThreadPoolExecutor instead of ThreadPoolExecutor
-java.util.concurrent.ThreadPoolExecutor#<init>(int,int,long,java.util.concurrent.TimeUnit,java.util.concurrent.BlockingQueue,java.util.concurrent.ThreadFactory,java.util.concurrent.RejectedExecutionHandler)
-java.util.concurrent.ThreadPoolExecutor#<init>(int,int,long,java.util.concurrent.TimeUnit,java.util.concurrent.BlockingQueue)
-java.util.concurrent.ThreadPoolExecutor#<init>(int,int,long,java.util.concurrent.TimeUnit,java.util.concurrent.BlockingQueue,java.util.concurrent.ThreadFactory)
-java.util.concurrent.ThreadPoolExecutor#<init>(int,int,long,java.util.concurrent.TimeUnit,java.util.concurrent.BlockingQueue,java.util.concurrent.RejectedExecutionHandler)
-
-@defaultMessage Use slf4j classes instead
-org.apache.log4j.**
-org.apache.logging.log4j.**
-java.util.logging.**
-
-@defaultMessage Use RTimer/TimeOut/System.nanoTime for time comparisons, and `new Date()` output/debugging/stats of timestamps. If for some miscellaneous reason, you absolutely need to use this, use a SuppressForbidden.
-java.lang.System#currentTimeMillis()
-
-@defaultMessage Use corresponding Java 8 functional/streaming interfaces
-com.google.common.base.Function
-com.google.common.base.Joiner
-com.google.common.base.Predicate
-com.google.common.base.Supplier
-
-@defaultMessage Use java.nio.charset.StandardCharsets instead
-com.google.common.base.Charsets
-org.apache.commons.codec.Charsets
-
-@defaultMessage Use methods in java.util.Objects instead
-com.google.common.base.Objects#equal(java.lang.Object,java.lang.Object)
-com.google.common.base.Objects#hashCode(java.lang.Object[])
-com.google.common.base.Preconditions#checkNotNull(java.lang.Object)
-com.google.common.base.Preconditions#checkNotNull(java.lang.Object,java.lang.Object)
-
-@defaultMessage Use methods in java.util.Comparator instead
-com.google.common.collect.Ordering
-
-@defaultMessage Use org.apache.solr.common.annotation.JsonProperty  instead
-com.fasterxml.jackson.annotation.JsonProperty
-
-
diff --git a/lucene/tools/forbiddenApis/tests.txt b/lucene/tools/forbiddenApis/tests.txt
deleted file mode 100644
index fbcc0dd..0000000
--- a/lucene/tools/forbiddenApis/tests.txt
+++ /dev/null
@@ -1,29 +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.
-
-junit.framework.TestCase @ All classes should derive from LuceneTestCase
-
-java.util.Random#<init>() @ Use RandomizedRunner's random() instead
-java.lang.Math#random() @ Use RandomizedRunner's random().nextDouble() instead
-
-# TODO: fix tests that do this!
-#java.lang.System#currentTimeMillis() @ Don't depend on wall clock times
-#java.lang.System#nanoTime() @ Don't depend on wall clock times
-
-com.carrotsearch.randomizedtesting.annotations.Seed @ Don't commit hardcoded seeds
-
-@defaultMessage Use LuceneTestCase.collate instead, which can avoid JDK-8071862
-java.text.Collator#compare(java.lang.Object,java.lang.Object)
-java.text.Collator#compare(java.lang.String,java.lang.String)
diff --git a/lucene/tools/ivy.xml b/lucene/tools/ivy.xml
deleted file mode 100644
index 1fa2974..0000000
--- a/lucene/tools/ivy.xml
+++ /dev/null
@@ -1,29 +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.    
--->
-<ivy-module version="2.0">
-  <info organisation="org.apache.lucene" module="tools"/>
-  <configurations defaultconfmapping="compile->master">
-    <conf name="compile" transitive="false"/>
-  </configurations>
-  <dependencies>
-    <dependency org="org.apache.ant" name="ant" rev="${/org.apache.ant/ant}" conf="compile"/>
-    <dependency org="org.apache.ivy" name="ivy" rev="${/org.apache.ivy/ivy}" conf="compile"/>
-    <exclude org="*" ext="*" matcher="regexp" type="${ivy.exclude.types}"/>
-  </dependencies>
-</ivy-module>
diff --git a/lucene/tools/junit4/cached-timehints.txt b/lucene/tools/junit4/cached-timehints.txt
deleted file mode 100644
index e69de29..0000000
diff --git a/lucene/tools/src/groovy/check-working-copy.groovy b/lucene/tools/src/groovy/check-working-copy.groovy
deleted file mode 100644
index 079a18b..0000000
--- a/lucene/tools/src/groovy/check-working-copy.groovy
+++ /dev/null
@@ -1,61 +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.
- */
-
-/** Task script that is called by Ant's build.xml file:
- * Checks GIT working copy for unversioned or modified files.
- */
-
-import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.Project;
-import org.eclipse.jgit.api.Git;
-import org.eclipse.jgit.api.Status;
-import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
-import org.eclipse.jgit.errors.*;
-
-def setProjectPropertyFromSet = { prop, set ->
-  if (set) {
-    properties[prop] = '* ' + set.join(properties['line.separator'] + '* ');
-  }
-};
-
-try {
-  task.log('Initializing working copy...', Project.MSG_INFO);
-  final Repository repository = new FileRepositoryBuilder()
-    .setWorkTree(project.getBaseDir())
-    .setMustExist(true)
-    .build();
-
-  task.log('Checking working copy status...', Project.MSG_INFO);
-  final Status status = new Git(repository).status().call();
-  if (!status.isClean()) {
-    final SortedSet unversioned = new TreeSet(), modified = new TreeSet();
-    status.properties.each{ prop, val ->
-      if (val instanceof Set) {
-        if (prop in ['untracked', 'untrackedFolders', 'missing']) {
-          unversioned.addAll(val);
-        } else if (prop != 'ignoredNotInIndex') {
-          modified.addAll(val);
-        }
-      }
-    };
-    setProjectPropertyFromSet('wc.unversioned.files', unversioned);
-    setProjectPropertyFromSet('wc.modified.files', modified);
-  }
-} catch (RepositoryNotFoundException | NoWorkTreeException | NotSupportedException e) {
-  task.log('WARNING: Development directory is not a valid GIT checkout! Disabling checks...', Project.MSG_WARN);
-}
diff --git a/lucene/tools/src/groovy/install-markdown-filter.groovy b/lucene/tools/src/groovy/install-markdown-filter.groovy
deleted file mode 100644
index bd5ceb3..0000000
--- a/lucene/tools/src/groovy/install-markdown-filter.groovy
+++ /dev/null
@@ -1,61 +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.
- */
-
-/** Task script that is called by Ant's common-build.xml file:
- * Installs markdown filter into Ant.
- */
-
-import org.apache.tools.ant.AntTypeDefinition;
-import org.apache.tools.ant.ComponentHelper;
-import org.apache.tools.ant.filters.TokenFilter.ChainableReaderFilter;
-import com.vladsch.flexmark.util.ast.Document;
-import com.vladsch.flexmark.ast.Heading;
-import com.vladsch.flexmark.html.HtmlRenderer;
-import com.vladsch.flexmark.parser.Parser;
-import com.vladsch.flexmark.parser.ParserEmulationProfile;
-import com.vladsch.flexmark.util.html.Escaping;
-import com.vladsch.flexmark.util.options.MutableDataSet;
-import com.vladsch.flexmark.ext.abbreviation.AbbreviationExtension;
-import com.vladsch.flexmark.ext.autolink.AutolinkExtension;
-
-public final class MarkdownFilter extends ChainableReaderFilter {
-  @Override
-  public String filter(String markdownSource) {
-    MutableDataSet options = new MutableDataSet();
-    options.setFrom(ParserEmulationProfile.MARKDOWN);
-    options.set(Parser.EXTENSIONS, [ AbbreviationExtension.create(), AutolinkExtension.create() ]);
-    options.set(HtmlRenderer.RENDER_HEADER_ID, true);
-    options.set(HtmlRenderer.MAX_TRAILING_BLANK_LINES, 0);
-    Document parsed = Parser.builder(options).build().parse(markdownSource);
-
-    StringBuilder html = new StringBuilder('<html>\n<head>\n');
-    CharSequence title = parsed.getFirstChildAny(Heading.class)?.getText();          
-    if (title != null) {
-      html.append('<title>').append(Escaping.escapeHtml(title, false)).append('</title>\n');
-    }
-    html.append('<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">\n')
-      .append('</head>\n<body>\n');
-    HtmlRenderer.builder(options).build().render(parsed, html);
-    html.append('</body>\n</html>\n');
-    return html;
-  }
-}
-
-AntTypeDefinition t = new AntTypeDefinition();
-t.setName('markdownfilter');
-t.setClass(MarkdownFilter.class);
-ComponentHelper.getComponentHelper(project).addDataTypeDefinition(t);
diff --git a/lucene/tools/src/groovy/run-beaster.groovy b/lucene/tools/src/groovy/run-beaster.groovy
deleted file mode 100644
index 057c147..0000000
--- a/lucene/tools/src/groovy/run-beaster.groovy
+++ /dev/null
@@ -1,121 +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.
- */
-
-/** Task script that is called by Ant's common-build.xml file:
- * Runs test beaster.
- */
-
-import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.BuildLogger;
-import org.apache.tools.ant.Project;
-
-
-static boolean logFailOutput(Object task, String outdir) {
-  def logFile = new File(outdir, "tests-failures.txt");
-  if (logFile.exists()) {
-    logFile.eachLine("UTF-8", { line ->
-      task.log(line, Project.MSG_ERR);
-    });
-  }
-}
-
-int iters = (properties['beast.iters'] ?: '1') as int;
-if (iters <= 1) {
-  throw new BuildException("Please give -Dbeast.iters with an int value > 1.");
-}
-
-def antcall = project.createTask('antcallback');
-
-def junitOutDir = properties["junit.output.dir"];
-
-def failed = false;
-
-(1..iters).each { i ->
-
-  def outdir = junitOutDir + "/" + i;
-  task.log('Beast round ' + i + " results: " + outdir, Project.MSG_INFO);
-  
-  try {
-    // disable verbose build logging:
-    project.buildListeners.each { listener ->
-      if (listener instanceof BuildLogger) {
-        listener.messageOutputLevel = Project.MSG_WARN;
-      }
-    };
-    
-    new File(outdir).mkdirs();
-    
-    properties["junit.output.dir"] = outdir;
-    
-    antcall.setReturn("tests.failed");
-    antcall.setTarget("-test");
-    antcall.setInheritAll(true);
-    antcall.setInheritRefs(true);
-    
-    antcall.with {
-
-      createParam().with {
-        name = "tests.isbeasting";
-        value = "true";
-      };
-      createParam().with {
-        name = "tests.timeoutSuite";
-        value = "900000";
-      };
-      createParam().with {
-        name = "junit.output.dir";
-        value = outdir;
-      };
-
-    };
-    
-    properties["junit.output.dir"] = outdir;
-
-    antcall.execute();
-
-    def antcallResult = project.properties.'tests.failed' as boolean;
-
-    if (antcallResult) {
-      failed = true;
-      logFailOutput(task, outdir)
-    }
-    
-  } catch (BuildException be) {
-    task.log(be.getMessage(), Project.MSG_ERR);
-    logFailOutput(task, outdir)
-    throw be;
-  } finally {
-    // restore build logging (unfortunately there is no way to get the original logging level (write-only property):
-    project.buildListeners.each { listener ->
-      if (listener instanceof BuildLogger) {
-        listener.messageOutputLevel = Project.MSG_INFO;
-      }
-    };
-  }
-};
-
-// restore junit output dir
-properties["junit.output.dir"] = junitOutDir;
-
-
-if (failed) {
-  task.log('Beasting finished with failure.', Project.MSG_INFO);
-  throw new BuildException("Beasting Failed!");
-} else {
-  task.log('Beasting finished Successfully.', Project.MSG_INFO);
-}
-
diff --git a/lucene/tools/src/groovy/run-maven-build.groovy b/lucene/tools/src/groovy/run-maven-build.groovy
deleted file mode 100644
index e241837..0000000
--- a/lucene/tools/src/groovy/run-maven-build.groovy
+++ /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.
- */
-
-/** Task script that is called by Ant's build.xml file:
- * Runs maven build from within Ant after creating POMs.
- */
-
-import groovy.xml.NamespaceBuilder;
-import org.apache.tools.ant.Project;
-
-def userHome = properties['user.home'], commonDir = properties['common.dir'];
-def propPrefix = '-mvn.inject.'; int propPrefixLen = propPrefix.length();
-
-def subProject = project.createSubProject();
-project.copyUserProperties(subProject);
-subProject.initProperties();
-new AntBuilder(subProject).sequential{
-  property(file: userHome+'/lucene.build.properties', prefix: propPrefix);
-  property(file: userHome+'/build.properties', prefix: propPrefix);
-  property(file: commonDir+'/build.properties', prefix: propPrefix);
-};
-
-def cmdlineProps = subProject.properties
-  .findAll{ k, v -> k.startsWith(propPrefix) }
-  .collectEntries{ k, v -> [k.substring(propPrefixLen), v] };
-cmdlineProps << project.userProperties.findAll{ k, v -> !k.startsWith('ant.') };
-
-def artifact = NamespaceBuilder.newInstance(ant, 'antlib:org.apache.maven.artifact.ant');
-
-task.log('Running Maven with props: ' + cmdlineProps.toString(), Project.MSG_INFO);
-artifact.mvn(pom: properties['maven-build-dir']+'/pom.xml', mavenVersion: properties['maven-version'], failonerror: true, fork: true) {
-  sysproperty(key: 'maven.multiModuleProjectDirectory', file: properties['maven-build-dir'])
-  cmdlineProps.each{ k, v -> arg(value: '-D' + k + '=' + v) };
-  arg(value: '-fae');
-  arg(value: 'install');
-};
diff --git a/lucene/tools/src/java/lucene-solr.antlib.xml b/lucene/tools/src/java/lucene-solr.antlib.xml
deleted file mode 100644
index 94a102d..0000000
--- a/lucene/tools/src/java/lucene-solr.antlib.xml
+++ /dev/null
@@ -1,27 +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.
- -->
-<antlib>
-    <taskdef 
-        name="licenses" 
-        classname="org.apache.lucene.validation.LicenseCheckTask" />
-    <taskdef
-        name="libversions"
-        classname="org.apache.lucene.validation.LibVersionsCheckTask" />
-    <taskdef
-        name="mvndeps"
-        classname="org.apache.lucene.dependencies.GetMavenDependenciesTask" />
-</antlib> 
diff --git a/lucene/tools/src/java/org/apache/lucene/dependencies/GetMavenDependenciesTask.java b/lucene/tools/src/java/org/apache/lucene/dependencies/GetMavenDependenciesTask.java
deleted file mode 100644
index 570016c..0000000
--- a/lucene/tools/src/java/org/apache/lucene/dependencies/GetMavenDependenciesTask.java
+++ /dev/null
@@ -1,920 +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.lucene.dependencies;
-
-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.FileResource;
-import org.apache.tools.ant.types.resources.Resources;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.NodeList;
-import org.xml.sax.SAXException;
-
-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.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.io.Reader;
-import java.io.Writer;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-import java.util.SortedMap;
-import java.util.SortedSet;
-import java.util.TreeMap;
-import java.util.TreeSet;
-import java.util.function.Consumer;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.xpath.XPath;
-import javax.xml.xpath.XPathConstants;
-import javax.xml.xpath.XPathExpressionException;
-import javax.xml.xpath.XPathFactory;
-
-/**
- * An Ant task to generate a properties file containing maven dependency
- * declarations, used to filter the maven POMs when copying them to
- * maven-build/ via 'ant get-maven-poms', or to lucene/build/poms/
- * via the '-filter-maven-poms' target, which is called from the
- * 'generate-maven-artifacts' target.
- */
-public class GetMavenDependenciesTask extends Task {
-  private static final Pattern PROPERTY_PREFIX_FROM_IVY_XML_FILE_PATTERN = Pattern.compile
-      ("[/\\\\](lucene|solr)[/\\\\](?:(?:contrib|(analysis)|(example)|(server))[/\\\\])?([^/\\\\]+)[/\\\\]ivy\\.xml");
-  private static final Pattern COORDINATE_KEY_PATTERN = Pattern.compile("/([^/]+)/([^/]+)");
-  private static final Pattern MODULE_DEPENDENCIES_COORDINATE_KEY_PATTERN
-      = Pattern.compile("(.*?)(\\.test)?\\.dependencies");
-  // lucene/build/core/classes/java
-  private static final Pattern COMPILATION_OUTPUT_DIRECTORY_PATTERN 
-      = Pattern.compile("(lucene|solr)/build/(?:contrib/)?(.*)/classes/(?:java|test)");
-  private static final String UNWANTED_INTERNAL_DEPENDENCIES
-      = "/(?:test-)?lib/|test-framework/classes/java|/test-files|/resources";
-  private static final Pattern SHARED_EXTERNAL_DEPENDENCIES_PATTERN
-      = Pattern.compile("((?:solr|lucene)/(?!test-framework).*)/((?:test-)?)lib/");
-
-  private static final String DEPENDENCY_MANAGEMENT_PROPERTY = "lucene.solr.dependency.management";
-  private static final String IVY_USER_DIR_PROPERTY = "ivy.default.ivy.user.dir";
-  private static final Properties allProperties = new Properties();
-  private static final Set<String> modulesWithSeparateCompileAndTestPOMs = new HashSet<>();
-
-  private static final Set<String> globalOptionalExternalDependencies = new HashSet<>();
-  private static final Map<String,Set<String>> perModuleOptionalExternalDependencies = new HashMap<>();
-  private static final Set<String> modulesWithTransitiveDependencies = new HashSet<>();
-  static {
-    // Add modules here that have split compile and test POMs
-    // - they need compile-scope deps to also be test-scope deps.
-    modulesWithSeparateCompileAndTestPOMs.addAll
-        (Arrays.asList("lucene-core", "lucene-codecs", "solr-core", "solr-solrj"));
-
-    // Add external dependencies here that should be optional for all modules
-    // (i.e., not invoke Maven's transitive dependency mechanism).
-    // Format is "groupId:artifactId"
-    globalOptionalExternalDependencies.addAll(Arrays.asList
-        ("org.slf4j:jul-to-slf4j", "org.slf4j:slf4j-log4j12"));
-
-    // Add modules here that should NOT have their dependencies
-    // excluded in the grandparent POM's dependencyManagement section,
-    // thus enabling their dependencies to be transitive.
-    modulesWithTransitiveDependencies.addAll(Arrays.asList("lucene-test-framework"));
-  }
-
-  private final XPath xpath = XPathFactory.newInstance().newXPath();
-  private final SortedMap<String,SortedSet<String>> internalCompileScopeDependencies
-      = new TreeMap<>();
-  private final Set<String> nonJarDependencies = new HashSet<>();
-  private final Map<String,Set<String>> dependencyClassifiers = new HashMap<>();
-  private final Map<String,Set<String>> interModuleExternalCompileScopeDependencies = new HashMap<>();
-  private final Map<String,Set<String>> interModuleExternalTestScopeDependencies = new HashMap<>();
-  private final Map<String,SortedSet<ExternalDependency>> allExternalDependencies
-     = new HashMap<>();
-  private final DocumentBuilder documentBuilder;
-  private File ivyCacheDir;
-  private Pattern internalJarPattern;
-  private Map<String,String> ivyModuleInfo;
-
-
-  /**
-   * All ivy.xml files to get external dependencies from.
-   */
-  private Resources ivyXmlResources = new Resources();
-
-  /**
-   * Centralized Ivy versions properties file
-   */
-  private File centralizedVersionsFile;
-
-  /**
-   * Module dependencies properties file, generated by task -append-module-dependencies-properties.
-   */
-  private File moduleDependenciesPropertiesFile;
-
-  /**
-   * Where all properties are written, to be used to filter POM templates when copying them.
-   */
-  private File mavenDependenciesFiltersFile;
-
-  /**
-   * A logging level associated with verbose logging.
-   */
-  private int verboseLevel = Project.MSG_VERBOSE;
-
-  /**
-   * Adds a set of ivy.xml resources to check.
-   */
-  public void add(ResourceCollection rc) {
-    ivyXmlResources.add(rc);
-  }
-
-  public void setVerbose(boolean verbose) {
-    verboseLevel = (verbose ? Project.MSG_VERBOSE : Project.MSG_INFO);
-  }
-
-  public void setCentralizedVersionsFile(File file) {
-    centralizedVersionsFile = file;
-  }
-
-  public void setModuleDependenciesPropertiesFile(File file) {
-    moduleDependenciesPropertiesFile = file;
-  }
-  
-  public void setMavenDependenciesFiltersFile(File file) {
-    mavenDependenciesFiltersFile = file;
-  }
-
-  public GetMavenDependenciesTask() {
-    try {
-      documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
-    } catch (ParserConfigurationException e) {
-      throw new BuildException(e);
-    }
-  }
-  
-  /**
-   * Collect dependency information from Ant build.xml and ivy.xml files
-   * and from ivy-versions.properties, then write out an Ant filters file
-   * to be used when copying POMs.
-   */
-  @Override
-  public void execute() throws BuildException {
-    // Local:   lucene/build/analysis/common/lucene-analyzers-common-5.0-SNAPSHOT.jar
-    // Jenkins: lucene/build/analysis/common/lucene-analyzers-common-5.0-2013-10-31_18-52-24.jar
-    // Also support any custom version, which won't necessarily conform to any predefined pattern.
-    internalJarPattern = Pattern.compile(".*(lucene|solr)([^/]*?)-"
-        + Pattern.quote(getProject().getProperty("version")) + "\\.jar");
-
-    ivyModuleInfo = getIvyModuleInfo(ivyXmlResources, documentBuilder, xpath);
-
-    setInternalDependencyProperties();            // side-effect: all modules' internal deps are recorded
-    setExternalDependencyProperties();            // side-effect: all modules' external deps are recorded
-    setGrandparentDependencyManagementProperty(); // uses deps recorded in above two methods
-    writeFiltersFile();
-  }
-
-  /**
-   * Write out an Ant filters file to be used when copying POMs.
-   */
-  private void writeFiltersFile() {
-    Writer writer = null;
-    try {
-      FileOutputStream outputStream = new FileOutputStream(mavenDependenciesFiltersFile);
-      writer = new OutputStreamWriter(outputStream, StandardCharsets.ISO_8859_1);
-      allProperties.store(writer, null);
-    } catch (FileNotFoundException e) {
-      throw new BuildException("Can't find file: '" + mavenDependenciesFiltersFile.getPath() + "'", e);
-    } catch (IOException e) {
-      throw new BuildException("Exception writing out '" + mavenDependenciesFiltersFile.getPath() + "'", e);
-    } finally {
-      if (null != writer) {
-        try {
-          writer.close();
-        } catch (IOException e) {
-          // ignore
-        }
-      }
-    }
-  }
-
-  /**
-   * Visits all ivy.xml files and collects module and organisation attributes into a map.
-   */
-  private static Map<String,String> getIvyModuleInfo(Resources ivyXmlResources,
-      DocumentBuilder documentBuilder, XPath xpath) {
-    Map<String,String> ivyInfoModuleToOrganisation = new HashMap<String,String>();
-    traverseIvyXmlResources(ivyXmlResources, new Consumer<File>() {
-      @Override
-      public void accept(File f) {
-        try {
-          Document document = documentBuilder.parse(f);
-          {
-            String infoPath = "/ivy-module/info";
-            NodeList infos = (NodeList)xpath.evaluate(infoPath, document, XPathConstants.NODESET);
-            for (int infoNum = 0 ; infoNum < infos.getLength() ; ++infoNum) {
-              Element infoElement = (Element)infos.item(infoNum);
-              String infoOrg = infoElement.getAttribute("organisation");
-              String infoOrgSuffix = infoOrg.substring(infoOrg.lastIndexOf('.')+1);
-              String infoModule = infoElement.getAttribute("module");
-              String module = infoOrgSuffix+"-"+infoModule;
-              ivyInfoModuleToOrganisation.put(module, infoOrg);
-            }
-          }
-        } catch (XPathExpressionException | IOException | SAXException e) {
-          throw new RuntimeException(e);
-        }
-      }
-    });
-    return ivyInfoModuleToOrganisation;
-  }
-
-  /**
-   * Collects external dependencies from each ivy.xml file and sets
-   * external dependency properties to be inserted into modules' POMs. 
-   */
-  private void setExternalDependencyProperties() {
-    traverseIvyXmlResources(ivyXmlResources, new Consumer<File>() {
-      @Override
-      public void accept(File f) {
-        try {
-        collectExternalDependenciesFromIvyXmlFile(f);
-        } catch (XPathExpressionException | IOException | SAXException e) {
-          throw new RuntimeException(e);
-        }
-      }
-    });
-    addSharedExternalDependencies();
-    setExternalDependencyXmlProperties();
-  }
-
-  private static void traverseIvyXmlResources(Resources ivyXmlResources, Consumer<File> ivyXmlFileConsumer) {
-    @SuppressWarnings("unchecked")
-    Iterator<Resource> iter = (Iterator<Resource>)ivyXmlResources.iterator();
-    while (iter.hasNext()) {
-      final Resource resource = iter.next();
-      if ( ! resource.isExists()) {
-        throw new BuildException("Resource does not exist: " + resource.getName());
-      }
-      if ( ! (resource instanceof FileResource)) {
-        throw new BuildException("Only filesystem resources are supported: "
-            + resource.getName() + ", was: " + resource.getClass().getName());
-      }
-
-      File ivyXmlFile = ((FileResource)resource).getFile();
-      try {
-        ivyXmlFileConsumer.accept(ivyXmlFile);
-      } catch (BuildException e) {
-        throw e;
-      } catch (Exception e) {
-        throw new BuildException("Exception reading file " + ivyXmlFile.getPath() + ": " + e, e);
-      }
-    }
-  }
-
-  /**
-   * For each module that includes other modules' external dependencies via
-   * including all files under their ".../lib/" dirs in their (test.)classpath,
-   * add the other modules' dependencies to its set of external dependencies. 
-   */
-  private void addSharedExternalDependencies() {
-    // Delay adding shared compile-scope dependencies until after all have been processed,
-    // so dependency sharing is limited to a depth of one.
-    Map<String,SortedSet<ExternalDependency>> sharedDependencies = new HashMap<>();
-    for (Map.Entry<String, Set<String>> entry : interModuleExternalCompileScopeDependencies.entrySet()) {
-      TreeSet<ExternalDependency> deps = new TreeSet<>();
-      sharedDependencies.put(entry.getKey(), deps);
-      Set<String> moduleDependencies = entry.getValue();
-      if (null != moduleDependencies) {
-        for (String otherArtifactId : moduleDependencies) {
-          SortedSet<ExternalDependency> otherExtDeps = allExternalDependencies.get(otherArtifactId); 
-          if (null != otherExtDeps) {
-            for (ExternalDependency otherDep : otherExtDeps) {
-              if ( ! otherDep.isTestDependency) {
-                deps.add(otherDep);
-              }
-            }
-          }
-        }
-      }
-    }
-    for (Map.Entry<String, Set<String>> entry : interModuleExternalTestScopeDependencies.entrySet()) {
-      String module = entry.getKey();
-      SortedSet<ExternalDependency> deps = sharedDependencies.get(module);
-      if (null == deps) {
-        deps = new TreeSet<>();
-        sharedDependencies.put(module, deps);
-      }
-      Set<String> moduleDependencies = entry.getValue();
-      if (null != moduleDependencies) {
-        for (String otherArtifactId : moduleDependencies) {
-          int testScopePos = otherArtifactId.indexOf(":test");
-          boolean isTestScope = false;
-          if (-1 != testScopePos) {
-            otherArtifactId = otherArtifactId.substring(0, testScopePos);
-            isTestScope = true;
-          }
-          SortedSet<ExternalDependency> otherExtDeps = allExternalDependencies.get(otherArtifactId);
-          if (null != otherExtDeps) {
-            for (ExternalDependency otherDep : otherExtDeps) {
-              if (otherDep.isTestDependency == isTestScope) {
-                if (  ! deps.contains(otherDep)
-                   && (  null == allExternalDependencies.get(module)
-                      || ! allExternalDependencies.get(module).contains(otherDep))) {
-                  // Add test-scope clone only if it's not already a compile-scope dependency. 
-                  ExternalDependency otherDepTestScope = new ExternalDependency
-                      (otherDep.groupId, otherDep.artifactId, otherDep.classifier, true, otherDep.isOptional);
-                  deps.add(otherDepTestScope);
-                }
-              }
-            }
-          }
-        }
-      }
-    }
-    for (Map.Entry<String, SortedSet<ExternalDependency>> entry : sharedDependencies.entrySet()) {
-      String module = entry.getKey();
-      SortedSet<ExternalDependency> deps = allExternalDependencies.get(module);
-      if (null == deps) {
-        deps = new TreeSet<>();
-        allExternalDependencies.put(module, deps);
-      }
-      for (ExternalDependency dep : entry.getValue()) {
-        String dependencyCoordinate = dep.groupId + ":" + dep.artifactId;
-        if (globalOptionalExternalDependencies.contains(dependencyCoordinate)
-            || (perModuleOptionalExternalDependencies.containsKey(module)
-                && perModuleOptionalExternalDependencies.get(module).contains(dependencyCoordinate))) {
-          // make a copy of the dep and set optional=true
-          dep = new ExternalDependency(dep.groupId, dep.artifactId, dep.classifier, dep.isTestDependency, true);
-        }
-        deps.add(dep);
-      }
-    }
-  }
-
-  /**
-   * For each module, sets a compile-scope and a test-scope property
-   * with values that contain the appropriate &lt;dependency&gt;
-   * snippets.
-   */
-  private void setExternalDependencyXmlProperties() {
-    for (String module : internalCompileScopeDependencies.keySet()) { // get full module list
-      StringBuilder compileScopeBuilder = new StringBuilder();
-      StringBuilder testScopeBuilder = new StringBuilder();
-      SortedSet<ExternalDependency> extDeps = allExternalDependencies.get(module);
-      if (null != extDeps) {
-        for (ExternalDependency dep : extDeps) {
-          StringBuilder builder = dep.isTestDependency ? testScopeBuilder : compileScopeBuilder;
-          appendDependencyXml(builder, dep.groupId, dep.artifactId, "    ", null, 
-                              dep.isTestDependency, dep.isOptional, dep.classifier, null);
-          // Test POMs for solrj, solr-core, lucene-codecs and lucene-core modules
-          // need to include all compile-scope dependencies as test-scope dependencies
-          // since we've turned off transitive dependency resolution.
-          if ( ! dep.isTestDependency && modulesWithSeparateCompileAndTestPOMs.contains(module)) {
-            appendDependencyXml(testScopeBuilder, dep.groupId, dep.artifactId, "    ", null,
-                                true, dep.isOptional, dep.classifier, null);
-          }
-        }
-      }
-      if (compileScopeBuilder.length() > 0) {
-        compileScopeBuilder.setLength(compileScopeBuilder.length() - 1); // drop trailing newline
-      }
-      if (testScopeBuilder.length() > 0) {
-        testScopeBuilder.setLength(testScopeBuilder.length() - 1); // drop trailing newline
-      }
-      allProperties.setProperty(module + ".external.dependencies", compileScopeBuilder.toString());
-      allProperties.setProperty(module + ".external.test.dependencies", testScopeBuilder.toString());
-    }
-  }
-
-  /**
-   * Sets the property to be inserted into the grandparent POM's 
-   * &lt;dependencyManagement&gt; section.
-   */
-  private void setGrandparentDependencyManagementProperty() {
-    StringBuilder builder = new StringBuilder();
-    appendAllInternalDependencies(builder);
-    Map<String,String> versionsMap = new HashMap<>();
-    appendAllExternalDependencies(builder, versionsMap);
-    builder.setLength(builder.length() - 1); // drop trailing newline
-    allProperties.setProperty(DEPENDENCY_MANAGEMENT_PROPERTY, builder.toString());
-    for (Map.Entry<String,String> entry : versionsMap.entrySet()) {
-      allProperties.setProperty(entry.getKey(), entry.getValue());
-    }
-  }
-
-  /**
-   * For each artifact in the project, append a dependency with version
-   * ${project.version} to the grandparent POM's &lt;dependencyManagement&gt;
-   * section.  An &lt;exclusion&gt; is added for each of the artifact's
-   * dependencies.
-   */
-  private void appendAllInternalDependencies(StringBuilder builder) {
-    for (Map.Entry<String, SortedSet<String>> entry : internalCompileScopeDependencies.entrySet()) {
-      String artifactId = entry.getKey();
-      List<String> exclusions = new ArrayList<>(entry.getValue());
-      SortedSet<ExternalDependency> extDeps = allExternalDependencies.get(artifactId);
-      if (null != extDeps) {
-        for (ExternalDependency externalDependency : extDeps) {
-          if ( ! externalDependency.isTestDependency && ! externalDependency.isOptional) {
-            exclusions.add(externalDependency.groupId + ':' + externalDependency.artifactId);
-          }
-        }
-      }
-      String groupId = ivyModuleInfo.get(artifactId);
-      appendDependencyXml(builder, groupId, artifactId, "      ", "${project.version}", false, false, null, exclusions);
-    }
-  }
-
-  /**
-   * Sets the ivyCacheDir field, to either the ${ivy.default.ivy.user.dir} 
-   * property, or if that's not set, to the default ~/.ivy2/.
-   */
-  private File getIvyCacheDir() {
-    String ivyUserDirName = getProject().getUserProperty(IVY_USER_DIR_PROPERTY);
-    if (null == ivyUserDirName) {
-      ivyUserDirName = getProject().getProperty(IVY_USER_DIR_PROPERTY);
-      if (null == ivyUserDirName) {
-        ivyUserDirName = System.getProperty("user.home") + System.getProperty("file.separator") + ".ivy2";
-      }
-    }
-    File ivyUserDir = new File(ivyUserDirName);
-    if ( ! ivyUserDir.exists()) {
-      throw new BuildException("Ivy user dir does not exist: '" + ivyUserDir.getPath() + "'");
-    }
-    File dir = new File(ivyUserDir, "cache");
-    if ( ! dir.exists()) {
-      throw new BuildException("Ivy cache dir does not exist: '" + ivyCacheDir.getPath() + "'");
-    }
-    return dir;
-  }
-
-  /**
-   * Append each dependency listed in the centralized Ivy versions file
-   * to the grandparent POM's &lt;dependencyManagement&gt; section.  
-   * An &lt;exclusion&gt; is added for each of the artifact's dependencies,
-   * which are collected from the artifact's ivy.xml from the Ivy cache.
-   * 
-   * Also add a version property for each dependency.
-   */
-  private void appendAllExternalDependencies(StringBuilder dependenciesBuilder, Map<String,String> versionsMap) {
-    log("Loading centralized ivy versions from: " + centralizedVersionsFile, verboseLevel);
-    ivyCacheDir = getIvyCacheDir();
-    Properties versions = new InterpolatedProperties();
-    try (InputStream inputStream = new FileInputStream(centralizedVersionsFile);
-         Reader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) {
-      versions.load(reader);
-    } catch (IOException e) {
-      throw new BuildException("Exception reading centralized versions file " + centralizedVersionsFile.getPath(), e);
-    } 
-    SortedSet<Map.Entry<?,?>> sortedEntries = new TreeSet<>(new Comparator<Map.Entry<?,?>>() {
-      @Override public int compare(Map.Entry<?,?> o1, Map.Entry<?,?> o2) {
-        return ((String)o1.getKey()).compareTo((String)o2.getKey());
-      }
-    });
-    sortedEntries.addAll(versions.entrySet());
-    for (Map.Entry<?,?> entry : sortedEntries) {
-      String key = (String)entry.getKey();
-      Matcher matcher = COORDINATE_KEY_PATTERN.matcher(key);
-      if (matcher.lookingAt()) {
-        String groupId = matcher.group(1);
-        String artifactId = matcher.group(2);
-        String coordinate = groupId + ':' + artifactId;
-        String version = (String)entry.getValue();
-        versionsMap.put(coordinate + ".version", version);
-        if ( ! nonJarDependencies.contains(coordinate)) {
-          Set<String> classifiers = dependencyClassifiers.get(coordinate);
-          if (null != classifiers) {
-            for (String classifier : classifiers) {
-              Collection<String> exclusions = getTransitiveDependenciesFromIvyCache(groupId, artifactId, version);
-              appendDependencyXml
-                  (dependenciesBuilder, groupId, artifactId, "      ", version, false, false, classifier, exclusions);
-            }
-          }
-        }
-      }
-    }
-  }
-
-  /**
-   * Collect transitive compile-scope dependencies for the given artifact's
-   * ivy.xml from the Ivy cache, using the default ivy pattern 
-   * "[organisation]/[module]/ivy-[revision].xml".  See 
-   * <a href="http://ant.apache.org/ivy/history/latest-milestone/settings/caches.html"
-   * >the Ivy cache documentation</a>.
-   */
-  private Collection<String> getTransitiveDependenciesFromIvyCache
-  (String groupId, String artifactId, String version) {
-    SortedSet<String> transitiveDependencies = new TreeSet<>();
-    //                                      E.g. ~/.ivy2/cache/xerces/xercesImpl/ivy-2.9.1.xml
-    File ivyXmlFile = new File(new File(new File(ivyCacheDir, groupId), artifactId), "ivy-" + version + ".xml");
-    if ( ! ivyXmlFile.exists()) {
-      throw new BuildException("File not found: " + ivyXmlFile.getPath());
-    }
-    try {
-      Document document = documentBuilder.parse(ivyXmlFile);
-      String dependencyPath = "/ivy-module/dependencies/dependency"
-                            + "[   not(starts-with(@conf,'test->'))"
-                            + "and not(starts-with(@conf,'provided->'))"
-                            + "and not(starts-with(@conf,'optional->'))]";
-      NodeList dependencies = (NodeList)xpath.evaluate(dependencyPath, document, XPathConstants.NODESET);
-      for (int i = 0 ; i < dependencies.getLength() ; ++i) {
-        Element dependency = (Element)dependencies.item(i);
-        transitiveDependencies.add(dependency.getAttribute("org") + ':' + dependency.getAttribute("name"));
-      }
-    } catch (Exception e) {
-      throw new BuildException( "Exception collecting transitive dependencies for " 
-                              + groupId + ':' + artifactId + ':' + version + " from "
-                              + ivyXmlFile.getAbsolutePath(), e);
-    }
-    return transitiveDependencies;
-  }
-
-  /**
-   * Sets the internal dependencies compile and test properties to be inserted 
-   * into modules' POMs.
-   * 
-   * Also collects shared external dependencies, 
-   * e.g. solr-core wants all of solrj's external dependencies 
-   */
-  private void  setInternalDependencyProperties() {
-    log("Loading module dependencies from: " + moduleDependenciesPropertiesFile, verboseLevel);
-    Properties moduleDependencies = new Properties();
-    try (InputStream inputStream = new FileInputStream(moduleDependenciesPropertiesFile);
-         Reader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) {
-      moduleDependencies.load(reader);
-    } catch (FileNotFoundException e) {
-      throw new BuildException("Properties file does not exist: " + moduleDependenciesPropertiesFile.getPath());
-    } catch (IOException e) {
-      throw new BuildException("Exception reading properties file " + moduleDependenciesPropertiesFile.getPath(), e);
-    }
-    Map<String,SortedSet<String>> testScopeDependencies = new HashMap<>();
-    Map<String, String> testScopePropertyKeys = new HashMap<>();
-    for (Map.Entry<?,?> entry : moduleDependencies.entrySet()) {
-      String newPropertyKey = (String)entry.getKey();
-      StringBuilder newPropertyValue = new StringBuilder();
-      String value = (String)entry.getValue();
-      Matcher matcher = MODULE_DEPENDENCIES_COORDINATE_KEY_PATTERN.matcher(newPropertyKey);
-      if ( ! matcher.matches()) {
-        throw new BuildException("Malformed module dependencies property key: '" + newPropertyKey + "'");
-      }
-      String antProjectName = matcher.group(1);
-      boolean isTest = null != matcher.group(2);
-      String artifactName = antProjectToArtifactName(antProjectName);
-      newPropertyKey = artifactName + (isTest ? ".internal.test" : ".internal") + ".dependencies"; // Add ".internal"
-      if (isTest) {
-        testScopePropertyKeys.put(artifactName, newPropertyKey);
-      }
-      if (null == value || value.isEmpty()) {
-        allProperties.setProperty(newPropertyKey, "");
-        Map<String,SortedSet<String>> scopedDependencies
-            = isTest ? testScopeDependencies : internalCompileScopeDependencies;
-        scopedDependencies.put(artifactName, new TreeSet<String>());
-      } else {
-        // Lucene analysis modules' build dirs do not include hyphens, but Solr contribs' build dirs do
-        String origModuleDir = antProjectName.replace("analyzers-", "analysis/");
-        // Exclude the module's own build output, in addition to UNWANTED_INTERNAL_DEPENDENCIES
-        Pattern unwantedInternalDependencies = Pattern.compile
-            ("(?:lucene/build/|solr/build/(?:contrib/)?)" + origModuleDir + "/" // require dir separator 
-             + "|" + UNWANTED_INTERNAL_DEPENDENCIES);
-        SortedSet<String> sortedDeps = new TreeSet<>();
-        for (String dependency : value.split(",")) {
-          matcher = SHARED_EXTERNAL_DEPENDENCIES_PATTERN.matcher(dependency);
-          if (matcher.find()) {
-            String otherArtifactName = matcher.group(1);
-            boolean isTestScope = null != matcher.group(2) && matcher.group(2).length() > 0;
-            otherArtifactName = otherArtifactName.replace('/', '-');
-            otherArtifactName = otherArtifactName.replace("lucene-analysis", "lucene-analyzers");
-            otherArtifactName = otherArtifactName.replace("solr-contrib-solr-", "solr-");
-            otherArtifactName = otherArtifactName.replace("solr-contrib-", "solr-");
-            if ( ! otherArtifactName.equals(artifactName)) {
-              Map<String,Set<String>> sharedDeps
-                  = isTest ? interModuleExternalTestScopeDependencies : interModuleExternalCompileScopeDependencies;
-              Set<String> sharedSet = sharedDeps.get(artifactName);
-              if (null == sharedSet) {
-                sharedSet = new HashSet<>();
-                sharedDeps.put(artifactName, sharedSet);
-              }
-              if (isTestScope) {
-                otherArtifactName += ":test";
-              }
-              sharedSet.add(otherArtifactName);
-            }
-          }
-          matcher = unwantedInternalDependencies.matcher(dependency);
-          if (matcher.find()) {
-            continue;  // skip external (/(test-)lib/), and non-jar and unwanted (self) internal deps
-          }
-          String artifactId = dependencyToArtifactId(newPropertyKey, dependency);
-          String groupId = ivyModuleInfo.get(artifactId);
-          String coordinate = groupId + ':' + artifactId;
-          sortedDeps.add(coordinate);
-        }
-        if (isTest) {  // Don't set test-scope properties until all compile-scope deps have been seen
-          testScopeDependencies.put(artifactName, sortedDeps);
-        } else {
-          internalCompileScopeDependencies.put(artifactName, sortedDeps);
-          for (String dependency : sortedDeps) {
-            int splitPos = dependency.indexOf(':');
-            String groupId = dependency.substring(0, splitPos);
-            String artifactId = dependency.substring(splitPos + 1);
-            appendDependencyXml(newPropertyValue, groupId, artifactId, "    ", null, false, false, null, null);
-          }
-          if (newPropertyValue.length() > 0) {
-            newPropertyValue.setLength(newPropertyValue.length() - 1); // drop trailing newline
-          }
-          allProperties.setProperty(newPropertyKey, newPropertyValue.toString());
-        }
-      }
-    }
-    // Now that all compile-scope dependencies have been seen, include only those test-scope
-    // dependencies that are not also compile-scope dependencies.
-    for (Map.Entry<String,SortedSet<String>> entry : testScopeDependencies.entrySet()) {
-      String module = entry.getKey();
-      SortedSet<String> testDeps = entry.getValue();
-      SortedSet<String> compileDeps = internalCompileScopeDependencies.get(module);
-      if (null == compileDeps) {
-        throw new BuildException("Can't find compile scope dependencies for module " + module);
-      }
-      StringBuilder newPropertyValue = new StringBuilder();
-      for (String dependency : testDeps) {
-        // modules with separate compile-scope and test-scope POMs need their compile-scope deps
-        // included in their test-scope deps.
-        if (modulesWithSeparateCompileAndTestPOMs.contains(module) || ! compileDeps.contains(dependency)) {
-          int splitPos = dependency.indexOf(':');
-          String groupId = dependency.substring(0, splitPos);
-          String artifactId = dependency.substring(splitPos + 1);
-          appendDependencyXml(newPropertyValue, groupId, artifactId, "    ", null, true, false, null, null);
-        }
-      }
-      if (newPropertyValue.length() > 0) {
-        newPropertyValue.setLength(newPropertyValue.length() - 1); // drop trailing newline
-      }
-      allProperties.setProperty(testScopePropertyKeys.get(module), newPropertyValue.toString());
-    }
-  }
-
-  /**
-   * Converts either a compile output directory or an internal jar
-   * dependency, taken from an Ant (test.)classpath, into an artifactId
-   */
-  private String dependencyToArtifactId(String newPropertyKey, String dependency) {
-    StringBuilder artifactId = new StringBuilder();
-    Matcher matcher = COMPILATION_OUTPUT_DIRECTORY_PATTERN.matcher(dependency);
-    if (matcher.matches()) {
-      // Pattern.compile("(lucene|solr)/build/(.*)/classes/java");
-      String artifact = matcher.group(2);
-      artifact = artifact.replace('/', '-');
-      artifact = artifact.replaceAll("(?<!solr-)analysis-", "analyzers-");
-      if ("lucene".equals(matcher.group(1))) {
-        artifactId.append("lucene-");
-      }
-      artifactId.append(artifact);
-    } else {
-      matcher = internalJarPattern.matcher(dependency);
-      if (matcher.matches()) {
-        // internalJarPattern is /.*(lucene|solr)([^/]*?)-<version>\.jar/,
-        // where <version> is the value of the Ant "version" property
-        artifactId.append(matcher.group(1));
-        artifactId.append(matcher.group(2));
-      } else {
-        throw new BuildException
-            ("Malformed module dependency from '" + newPropertyKey + "': '" + dependency + "'");
-      }
-    }
-    return artifactId.toString();
-  }
-
-  /**
-   * Convert Ant project names to artifact names: prepend "lucene-"
-   * to Lucene project names
-   */
-  private String antProjectToArtifactName(String origModule) {
-    String module = origModule;
-    if ( ! origModule.startsWith("solr-")) { // lucene modules names don't have "lucene-" prepended
-      module = "lucene-" + module;
-    }
-    return module;
-  }
-
-  /**
-   * Collect external dependencies from the given ivy.xml file, constructing
-   * property values containing &lt;dependency&gt; snippets, which will be
-   * filtered (substituted) when copying the POM for the module corresponding
-   * to the given ivy.xml file.
-   */
-  private void collectExternalDependenciesFromIvyXmlFile(File ivyXmlFile)
-      throws XPathExpressionException, IOException, SAXException {
-    String module = getModuleName(ivyXmlFile);
-    log("Collecting external dependencies from: " + ivyXmlFile.getPath(), verboseLevel);
-    Document document = documentBuilder.parse(ivyXmlFile);
-    // Exclude the 'start' configuration in solr/server/ivy.xml
-    String dependencyPath = "/ivy-module/dependencies/dependency[not(starts-with(@conf,'start'))]";
-    NodeList dependencies = (NodeList)xpath.evaluate(dependencyPath, document, XPathConstants.NODESET);
-    for (int depNum = 0 ; depNum < dependencies.getLength() ; ++depNum) {
-      Element dependency = (Element)dependencies.item(depNum);
-      String groupId = dependency.getAttribute("org");
-      String artifactId = dependency.getAttribute("name");
-      String dependencyCoordinate = groupId + ':' + artifactId;
-      Set<String> classifiers = dependencyClassifiers.get(dependencyCoordinate);
-      if (null == classifiers) {
-        classifiers = new HashSet<>();
-        dependencyClassifiers.put(dependencyCoordinate, classifiers);
-      }
-      String conf = dependency.getAttribute("conf");
-      boolean confContainsTest = conf.contains("test");
-      boolean isOptional = globalOptionalExternalDependencies.contains(dependencyCoordinate)
-          || ( perModuleOptionalExternalDependencies.containsKey(module)
-              && perModuleOptionalExternalDependencies.get(module).contains(dependencyCoordinate));
-      SortedSet<ExternalDependency> deps = allExternalDependencies.get(module);
-      if (null == deps) {
-        deps = new TreeSet<>();
-        allExternalDependencies.put(module, deps);
-      }
-      NodeList artifacts = null;
-      if (dependency.hasChildNodes()) {
-        artifacts = (NodeList)xpath.evaluate("artifact", dependency, XPathConstants.NODESET);
-      }
-      if (null != artifacts && artifacts.getLength() > 0) {
-        for (int artifactNum = 0 ; artifactNum < artifacts.getLength() ; ++artifactNum) {
-          Element artifact = (Element)artifacts.item(artifactNum);
-          String type = artifact.getAttribute("type");
-          String ext = artifact.getAttribute("ext");
-          // When conf contains BOTH "test" and "compile", and type != "test", this is NOT a test dependency
-          boolean isTestDependency = confContainsTest && (type.equals("test") || ! conf.contains("compile"));
-          if ((type.isEmpty() && ext.isEmpty()) || type.equals("jar") || ext.equals("jar")) {
-            String classifier = artifact.getAttribute("maven:classifier");
-            if (classifier.isEmpty()) {
-              classifier = null;
-            }
-            classifiers.add(classifier);
-            deps.add(new ExternalDependency(groupId, artifactId, classifier, isTestDependency, isOptional));
-          } else { // not a jar
-            nonJarDependencies.add(dependencyCoordinate);
-          }
-        }
-      } else {
-        classifiers.add(null);
-        deps.add(new ExternalDependency(groupId, artifactId, null, confContainsTest, isOptional));
-      }
-    }
-  }
-
-  /**
-   * Stores information about an external dependency
-   */
-  private static class ExternalDependency implements Comparable<ExternalDependency> {
-    String groupId;
-    String artifactId;
-    boolean isTestDependency;
-    boolean isOptional;
-    String classifier;
-    
-    public ExternalDependency
-        (String groupId, String artifactId, String classifier, boolean isTestDependency, boolean isOptional) {
-      this.groupId = groupId;
-      this.artifactId = artifactId;
-      this.classifier = classifier;
-      this.isTestDependency = isTestDependency;
-      this.isOptional = isOptional;
-    }
-    
-    @Override
-    public boolean equals(Object o) {
-      if ( ! (o instanceof ExternalDependency)) {
-        return false;
-      }
-      ExternalDependency other = (ExternalDependency)o;
-      return groupId.equals(other.groupId) 
-          && artifactId.equals(other.artifactId) 
-          && isTestDependency == other.isTestDependency
-          && isOptional == other.isOptional
-          && classifier.equals(other.classifier);
-    } 
-    
-    @Override
-    public int hashCode() {
-      return groupId.hashCode() * 31
-          + artifactId.hashCode() * 31
-          + (isTestDependency ? 31 : 0)
-          + (isOptional ? 31 : 0)
-          + classifier.hashCode();
-    }
-
-    @Override
-    public int compareTo(ExternalDependency other) {
-      int comparison = groupId.compareTo(other.groupId);
-      if (0 != comparison) {
-        return comparison;
-      }
-      comparison = artifactId.compareTo(other.artifactId);
-      if (0 != comparison) {
-        return comparison;
-      }
-      if (null == classifier) {
-        if (null != other.classifier) {
-          return -1;
-        }
-      } else if (null == other.classifier) { // classifier is not null
-        return 1;
-      } else {                               // neither classifier is  null
-        if (0 != (comparison = classifier.compareTo(other.classifier))) {
-          return comparison;
-        }
-      }
-      // test and optional don't matter in this sort
-      return 0;
-    }
-  }
-  
-  /**
-   * Extract module name from ivy.xml path.
-   */
-  private String getModuleName(File ivyXmlFile) {
-    String path = ivyXmlFile.getAbsolutePath();
-    Matcher matcher = PROPERTY_PREFIX_FROM_IVY_XML_FILE_PATTERN.matcher(path);
-    if ( ! matcher.find()) {
-      throw new BuildException("Can't get module name from ivy.xml path: " + path);
-    }
-    StringBuilder builder = new StringBuilder();
-    builder.append(matcher.group(1));
-    if (null != matcher.group(2)) { // "lucene/analysis/..."
-      builder.append("-analyzers");
-    } else if (null != matcher.group(3)) { // "solr/example/..."
-      builder.append("-example");
-    } else if (null != matcher.group(4)) { // "solr/server/..."
-      builder.append("-server");
-    }
-    builder.append('-');
-    builder.append(matcher.group(5));
-    return builder.toString().replace("solr-solr-", "solr-");
-  }
-
-/**
- * Appends a &lt;dependency&gt; snippet to the given builder.
- */
-  private void appendDependencyXml(StringBuilder builder, String groupId, String artifactId, 
-                                   String indent, String version, boolean isTestDependency, 
-                                   boolean isOptional, String classifier, Collection<String> exclusions) {
-    builder.append(indent).append("<dependency>\n");
-    builder.append(indent).append("  <groupId>").append(groupId).append("</groupId>\n");
-    builder.append(indent).append("  <artifactId>").append(artifactId).append("</artifactId>\n");
-    if (null != version) {
-      builder.append(indent).append("  <version>").append(version).append("</version>\n");
-    }
-    if (isTestDependency) {
-      builder.append(indent).append("  <scope>test</scope>\n");
-    }
-    if (isOptional) {
-      builder.append(indent).append("  <optional>true</optional>\n");
-    }
-    if (null != classifier) {
-      builder.append(indent).append("  <classifier>").append(classifier).append("</classifier>\n");
-    }
-    if ( ! modulesWithTransitiveDependencies.contains(artifactId) && null != exclusions && ! exclusions.isEmpty()) {
-      builder.append(indent).append("  <exclusions>\n");
-      for (String dependency : exclusions) {
-        int splitPos = dependency.indexOf(':');
-        String excludedGroupId = dependency.substring(0, splitPos);
-        String excludedArtifactId = dependency.substring(splitPos + 1);
-        builder.append(indent).append("    <exclusion>\n");
-        builder.append(indent).append("      <groupId>").append(excludedGroupId).append("</groupId>\n");
-        builder.append(indent).append("      <artifactId>").append(excludedArtifactId).append("</artifactId>\n");
-        builder.append(indent).append("    </exclusion>\n");
-      }
-      builder.append(indent).append("  </exclusions>\n");
-    }
-    builder.append(indent).append("</dependency>\n");
-  }
-}
diff --git a/lucene/tools/src/java/org/apache/lucene/dependencies/InterpolatedProperties.java b/lucene/tools/src/java/org/apache/lucene/dependencies/InterpolatedProperties.java
deleted file mode 100644
index 073db7b..0000000
--- a/lucene/tools/src/java/org/apache/lucene/dependencies/InterpolatedProperties.java
+++ /dev/null
@@ -1,162 +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.lucene.dependencies;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Reader;
-import java.util.Arrays;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.stream.Collectors;
-
-/**
- * Parse a properties file, performing recursive Ant-like
- * property value interpolation, and return the resulting Properties.
- */
-public class InterpolatedProperties extends Properties {
-  private static final Pattern PROPERTY_REFERENCE_PATTERN = Pattern.compile("\\$\\{(?<name>[^}]+)\\}");
-
-  /**
-   * Loads the properties file via {@link Properties#load(InputStream)},
-   * then performs recursive Ant-like property value interpolation.
-   */
-  @Override
-  public void load(InputStream inStream) throws IOException {
-    throw new UnsupportedOperationException("InterpolatedProperties.load(InputStream) is not supported.");
-  }
-
-  /**
-   * Loads the properties file via {@link Properties#load(Reader)},
-   * then performs recursive Ant-like property value interpolation.
-   */
-  @Override
-  public void load(Reader reader) throws IOException {
-    Properties p = new Properties();
-    p.load(reader);
-
-    LinkedHashMap<String, String> props = new LinkedHashMap<>();
-    Enumeration<?> e = p.propertyNames();
-    while (e.hasMoreElements()) {
-      String key = (String) e.nextElement();
-      props.put(key, p.getProperty(key));
-    }
-
-    resolve(props).forEach((k, v) -> this.setProperty(k, v));
-  }
-
-  private static Map<String,String> resolve(Map<String,String> props) {
-    LinkedHashMap<String, String> resolved = new LinkedHashMap<>();
-    HashSet<String> recursive = new HashSet<>();
-    props.forEach((k, v) -> {
-      resolve(props, resolved, recursive, k, v);
-    });
-    return resolved;
-  }
-
-  private static String resolve(Map<String,String> props,
-                               LinkedHashMap<String, String> resolved,
-                               Set<String> recursive,
-                               String key,
-                               String value) {
-    if (value == null) {
-      throw new IllegalArgumentException("Missing replaced property key: " + key);
-    }
-
-    if (recursive.contains(key)) {
-      throw new IllegalArgumentException("Circular recursive property resolution: " + recursive);
-    }
-
-    if (!resolved.containsKey(key)) {
-      recursive.add(key);
-      StringBuffer buffer = new StringBuffer();
-      Matcher matcher = PROPERTY_REFERENCE_PATTERN.matcher(value);
-      while (matcher.find()) {
-        String referenced = matcher.group("name");
-        String concrete = resolve(props, resolved, recursive, referenced, props.get(referenced));
-        matcher.appendReplacement(buffer, Matcher.quoteReplacement(concrete));
-      }
-      matcher.appendTail(buffer);
-      resolved.put(key, buffer.toString());
-      recursive.remove(key);
-    }
-    assert resolved.get(key).equals(value);
-    return resolved.get(key);
-  }
-
-  public static void main(String [] args) {
-    {
-      Map<String, String> props = new LinkedHashMap<>();
-      props.put("a", "${b}");
-      props.put("b", "${c}");
-      props.put("c", "foo");
-      props.put("d", "${a}/${b}/${c}");
-      assertEquals(resolve(props), "a=foo", "b=foo", "c=foo", "d=foo/foo/foo");
-    }
-
-    {
-      Map<String, String> props = new LinkedHashMap<>();
-      props.put("a", "foo");
-      props.put("b", "${a}");
-      assertEquals(resolve(props), "a=foo", "b=foo");
-    }
-
-    {
-      Map<String, String> props = new LinkedHashMap<>();
-      props.put("a", "${b}");
-      props.put("b", "${c}");
-      props.put("c", "${a}");
-      try {
-        resolve(props);
-      } catch (IllegalArgumentException e) {
-        // Expected, circular reference.
-        if (!e.getMessage().contains("Circular recursive")) {
-          throw new AssertionError();
-        }
-      }
-    }
-
-    {
-      Map<String, String> props = new LinkedHashMap<>();
-      props.put("a", "${b}");
-      try {
-        resolve(props);
-      } catch (IllegalArgumentException e) {
-        // Expected, no referenced value.
-        if (!e.getMessage().contains("Missing replaced")) {
-          throw new AssertionError();
-        }
-      }
-    }
-  }
-
-  private static void assertEquals(Map<String,String> resolved, String... keyValuePairs) {
-    List<String> result = resolved.entrySet().stream().sorted((a, b) -> a.getKey().compareTo(b.getKey()))
-        .map(e -> e.getKey() + "=" + e.getValue())
-        .collect(Collectors.toList());
-    if (!result.equals(Arrays.asList(keyValuePairs))) {
-      throw new AssertionError("Mismatch: \n" + result + "\nExpected: " + Arrays.asList(keyValuePairs));
-    }
-  }
-}
diff --git a/lucene/tools/src/java/org/apache/lucene/validation/LibVersionsCheckTask.java b/lucene/tools/src/java/org/apache/lucene/validation/LibVersionsCheckTask.java
deleted file mode 100644
index 2b89703..0000000
--- a/lucene/tools/src/java/org/apache/lucene/validation/LibVersionsCheckTask.java
+++ /dev/null
@@ -1,903 +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.lucene.validation;
-
-import org.apache.ivy.Ivy;
-import org.apache.ivy.core.LogOptions;
-import org.apache.ivy.core.report.ResolveReport;
-import org.apache.ivy.core.resolve.ResolveOptions;
-import org.apache.ivy.core.settings.IvySettings;
-import org.apache.ivy.plugins.conflict.NoConflictManager;
-import org.apache.lucene.dependencies.InterpolatedProperties;
-import org.apache.lucene.validation.ivyde.IvyNodeElement;
-import org.apache.lucene.validation.ivyde.IvyNodeElementAdapter;
-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.FileResource;
-import org.apache.tools.ant.types.resources.Resources;
-import org.xml.sax.Attributes;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-import org.xml.sax.SAXNotRecognizedException;
-import org.xml.sax.SAXNotSupportedException;
-import org.xml.sax.helpers.DefaultHandler;
-
-import javax.xml.XMLConstants;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.stream.StreamResult;
-import javax.xml.transform.stream.StreamSource;
-
-import java.io.BufferedReader;
-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.io.Reader;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.nio.charset.StandardCharsets;
-import java.text.ParseException;
-import java.util.Arrays;
-import java.util.Comparator;
-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.Stack;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * An Ant task to verify that the '/org/name' keys in ivy-versions.properties
- * are sorted lexically and are neither duplicates nor orphans, and that all
- * dependencies in all ivy.xml files use rev="${/org/name}" format.
- */
-public class LibVersionsCheckTask extends Task {
-
-  private static final String IVY_XML_FILENAME = "ivy.xml";
-  private static final Pattern COORDINATE_KEY_PATTERN = Pattern.compile("(/([^/ \t\f]+)/([^=:/ \t\f]+))");
-  private static final Pattern BLANK_OR_COMMENT_LINE_PATTERN = Pattern.compile("[ \t\f]*(?:[#!].*)?");
-  private static final Pattern TRAILING_BACKSLASH_PATTERN = Pattern.compile("[^\\\\]*(\\\\+)$");
-  private static final Pattern LEADING_WHITESPACE_PATTERN = Pattern.compile("[ \t\f]+(.*)");
-  private static final Pattern WHITESPACE_GOODSTUFF_WHITESPACE_BACKSLASH_PATTERN
-      = Pattern.compile("[ \t\f]*(.*?)(?:(?<!\\\\)[ \t\f]*)?\\\\");
-  private static final Pattern TRAILING_WHITESPACE_BACKSLASH_PATTERN
-      = Pattern.compile("(.*?)(?:(?<!\\\\)[ \t\f]*)?\\\\");
-  private static final Pattern MODULE_NAME_PATTERN = Pattern.compile("\\smodule\\s*=\\s*[\"']([^\"']+)[\"']");
-  private static final Pattern MODULE_DIRECTORY_PATTERN 
-      = Pattern.compile(".*[/\\\\]((?:lucene|solr)[/\\\\].*)[/\\\\].*");
-  private static final SAXParserFactory SAX_PARSER_FACTORY = SAXParserFactory.newDefaultInstance();
-  static {
-    try {
-      SAX_PARSER_FACTORY.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
-    } catch (SAXNotRecognizedException | SAXNotSupportedException | ParserConfigurationException e) {
-      throw new Error(e);
-    }
-  }
-  private Ivy ivy;
-
-  /**
-   * All ivy.xml files to check.
-   */
-  private Resources ivyXmlResources = new Resources();
-
-  /**
-   * Centralized Ivy versions properties file: ivy-versions.properties
-   */
-  private File centralizedVersionsFile;
-
-  /**
-   * Centralized Ivy ignore conflicts file: ivy-ignore-conflicts.properties
-   */
-  private File ignoreConflictsFile;
-
-  /**
-   * Ivy settings file: top-level-ivy-settings.xml
-   */
-  private File topLevelIvySettingsFile;
-
-  /**
-   * Location of common build dir: lucene/build/
-   */
-  private File commonBuildDir;
-
-  /**
-   * Location of ivy cache resolution directory.
-   */
-  private File ivyResolutionCacheDir;
-  
-  /**
-   * Artifact lock strategy that Ivy should use.
-   */
-  private String ivyLockStrategy;
-  
-  /**
-   * A logging level associated with verbose logging.
-   */
-  private int verboseLevel = Project.MSG_VERBOSE;
-  
-  /**
-   * All /org/name keys found in ivy-versions.properties,
-   * mapped to info about direct dependence and what would
-   * be conflicting indirect dependencies if Lucene/Solr
-   * were to use transitive dependencies.
-   */
-  private Map<String,Dependency> directDependencies = new LinkedHashMap<>();
-
-  /**
-   * All /org/name keys found in ivy-ignore-conflicts.properties,
-   * mapped to the set of indirect dependency versions that will
-   * be ignored, i.e. not trigger a conflict.
-   */
-  private Map<String,HashSet<String>> ignoreConflictVersions = new HashMap<>();
-
-  private static class Dependency {
-    String org;
-    String name;
-    String directVersion;
-    String latestVersion;
-    boolean directlyReferenced = false;
-    LinkedHashMap<IvyNodeElement,Set<String>> conflictLocations = new LinkedHashMap<>(); // dependency path -> moduleNames
-    
-    Dependency(String org, String name, String directVersion) {
-      this.org = org;
-      this.name = name;
-      this.directVersion = directVersion;
-    }
-  }
-  
-  /**
-   * Adds a set of ivy.xml resources to check.
-   */
-  public void add(ResourceCollection rc) {
-    ivyXmlResources.add(rc);
-  }
-
-  public void setVerbose(boolean verbose) {
-    verboseLevel = (verbose ? Project.MSG_INFO : Project.MSG_VERBOSE);
-  }
-
-  public void setCentralizedVersionsFile(File file) {
-    centralizedVersionsFile = file;
-  }
-
-  public void setTopLevelIvySettingsFile(File file) {
-    topLevelIvySettingsFile = file;
-  }
-
-  public void setIvyResolutionCacheDir(File dir) {
-    ivyResolutionCacheDir = dir;
-  }
-  
-  public void setIvyLockStrategy(String strategy) {
-    this.ivyLockStrategy = strategy;
-  }
-
-  public void setCommonBuildDir(File file) {
-    commonBuildDir = file;
-  }
-  
-  public void setIgnoreConflictsFile(File file) {
-    ignoreConflictsFile = file;
-  }
-
-  /**
-   * Execute the task.
-   */
-  @Override
-  public void execute() throws BuildException {
-    log("Starting scan.", verboseLevel);
-    long start = System.currentTimeMillis();
-
-    setupIvy();
-
-    int numErrors = 0;
-    if ( ! verifySortedCoordinatesPropertiesFile(centralizedVersionsFile)) {
-      ++numErrors;
-    }
-    if ( ! verifySortedCoordinatesPropertiesFile(ignoreConflictsFile)) {
-      ++numErrors;
-    }
-    collectDirectDependencies();
-    if ( ! collectVersionConflictsToIgnore()) {
-      ++numErrors;
-    }
-
-    int numChecked = 0;
-
-    @SuppressWarnings("unchecked")
-    Iterator<Resource> iter = (Iterator<Resource>)ivyXmlResources.iterator();
-    while (iter.hasNext()) {
-      final Resource resource = iter.next();
-      if ( ! resource.isExists()) {
-        throw new BuildException("Resource does not exist: " + resource.getName());
-      }
-      if ( ! (resource instanceof FileResource)) {
-        throw new BuildException("Only filesystem resources are supported: " 
-            + resource.getName() + ", was: " + resource.getClass().getName());
-      }
-
-      File ivyXmlFile = ((FileResource)resource).getFile();
-      try {
-        if ( ! checkIvyXmlFile(ivyXmlFile)) {
-          ++numErrors;
-        }
-        if ( ! resolveTransitively(ivyXmlFile)) {
-          ++numErrors;
-        }
-        if ( ! findLatestConflictVersions()) {
-          ++numErrors;
-        }
-      } catch (Exception e) {
-        throw new BuildException("Exception reading file " + ivyXmlFile.getPath() + " - " + e.toString(), e);
-      }
-      ++numChecked;
-    }
-
-    log("Checking for orphans in " + centralizedVersionsFile.getName(), verboseLevel);
-    for (Map.Entry<String,Dependency> entry : directDependencies.entrySet()) {
-      String coordinateKey = entry.getKey();
-      if ( ! entry.getValue().directlyReferenced) {
-        log("ORPHAN coordinate key '" + coordinateKey + "' in " + centralizedVersionsFile.getName()
-            + " is not found in any " + IVY_XML_FILENAME + " file.",
-            Project.MSG_ERR);
-        ++numErrors;
-      }
-    }
-
-    int numConflicts = emitConflicts();
-
-    int messageLevel = numErrors > 0 ? Project.MSG_ERR : Project.MSG_INFO;
-    log("Checked that " + centralizedVersionsFile.getName() + " and " + ignoreConflictsFile.getName()
-        + " have lexically sorted '/org/name' keys and no duplicates or orphans.",
-        messageLevel);
-    log("Scanned " + numChecked + " " + IVY_XML_FILENAME + " files for rev=\"${/org/name}\" format.",
-        messageLevel);
-    log("Found " + numConflicts + " indirect dependency version conflicts.");
-    log(String.format(Locale.ROOT, "Completed in %.2fs., %d error(s).",
-                      (System.currentTimeMillis() - start) / 1000.0, numErrors),
-        messageLevel);
-
-    if (numConflicts > 0 || numErrors > 0) {
-      throw new BuildException("Lib versions check failed. Check the logs.");
-    }
-  }
-
-  private boolean findLatestConflictVersions() {
-    boolean success = true;
-    StringBuilder latestIvyXml = new StringBuilder();
-    latestIvyXml.append("<ivy-module version=\"2.0\">\n");
-    latestIvyXml.append("  <info organisation=\"org.apache.lucene\" module=\"core-tools-find-latest-revision\"/>\n");
-    latestIvyXml.append("  <configurations>\n");
-    latestIvyXml.append("    <conf name=\"default\" transitive=\"false\"/>\n");
-    latestIvyXml.append("  </configurations>\n");
-    latestIvyXml.append("  <dependencies>\n");
-    for (Map.Entry<String, Dependency> directDependency : directDependencies.entrySet()) {
-      Dependency dependency = directDependency.getValue();
-      if (dependency.conflictLocations.entrySet().isEmpty()) {
-        continue;
-      }
-      latestIvyXml.append("    <dependency org=\"");
-      latestIvyXml.append(dependency.org);
-      latestIvyXml.append("\" name=\"");
-      latestIvyXml.append(dependency.name);
-      latestIvyXml.append("\" rev=\"latest.release\" conf=\"default->*\"/>\n");
-    }
-    latestIvyXml.append("  </dependencies>\n");
-    latestIvyXml.append("</ivy-module>\n");
-    File buildDir = new File(commonBuildDir, "ivy-transitive-resolve");
-    if ( ! buildDir.exists() && ! buildDir.mkdirs()) {
-      throw new BuildException("Could not create temp directory " + buildDir.getPath());
-    }
-    File findLatestIvyXmlFile = new File(buildDir, "find.latest.conflicts.ivy.xml");
-    try {
-      try (Writer writer = new OutputStreamWriter(new FileOutputStream(findLatestIvyXmlFile), StandardCharsets.UTF_8)) {
-        writer.write(latestIvyXml.toString());
-      }
-      ResolveOptions options = new ResolveOptions();
-      options.setDownload(false);           // Download only module descriptors, not artifacts
-      options.setTransitive(false);         // Resolve only direct dependencies
-      options.setUseCacheOnly(false);       // Download the internet!
-      options.setOutputReport(false);       // Don't print to the console
-      options.setLog(LogOptions.LOG_QUIET); // Don't log to the console
-      options.setConfs(new String[] {"*"}); // Resolve all configurations
-      ResolveReport resolveReport = ivy.resolve(findLatestIvyXmlFile.toURI().toURL(), options);
-      IvyNodeElement root = IvyNodeElementAdapter.adapt(resolveReport);
-      for (IvyNodeElement element : root.getDependencies()) {
-        String coordinate = "/" + element.getOrganization() + "/" + element.getName();
-        Dependency dependency = directDependencies.get(coordinate);
-        if (null == dependency) {
-          log("ERROR: the following coordinate key does not appear in "
-              + centralizedVersionsFile.getName() + ": " + coordinate, Project.MSG_ERR);
-          success = false;
-        } else {
-          dependency.latestVersion = element.getRevision();
-        }
-      }
-    } catch (IOException e) {
-      log("Exception writing to " + findLatestIvyXmlFile.getPath() + ": " + e.toString(), Project.MSG_ERR);
-      success = false;
-    } catch (ParseException e) {
-      log("Exception parsing filename " + findLatestIvyXmlFile.getPath() + ": " + e.toString(), Project.MSG_ERR);
-      success = false;
-    }
-    return success;
-  }
-
-  /**
-   * Collects indirect dependency version conflicts to ignore 
-   * in ivy-ignore-conflicts.properties, and also checks for orphans
-   * (coordinates not included in ivy-versions.properties).
-   * 
-   * Returns true if no orphans are found.
-   */
-  private boolean collectVersionConflictsToIgnore() {
-    log("Checking for orphans in " + ignoreConflictsFile.getName(), verboseLevel);
-    boolean orphansFound = false;
-    InterpolatedProperties properties = new InterpolatedProperties();
-    try (InputStream inputStream = new FileInputStream(ignoreConflictsFile);
-         Reader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) {
-      properties.load(reader);
-    } catch (IOException e) {
-      throw new BuildException("Exception reading " + ignoreConflictsFile + ": " + e.toString(), e);
-    }
-    for (Object obj : properties.keySet()) {
-      String coordinate = (String)obj;
-      if (COORDINATE_KEY_PATTERN.matcher(coordinate).matches()) {
-        if ( ! directDependencies.containsKey(coordinate)) {
-          orphansFound = true;
-          log("ORPHAN coordinate key '" + coordinate + "' in " + ignoreConflictsFile.getName()
-                  + " is not found in " + centralizedVersionsFile.getName(),
-              Project.MSG_ERR);
-        } else {
-          String versionsToIgnore = properties.getProperty(coordinate);
-          List<String> ignore = Arrays.asList(versionsToIgnore.trim().split("\\s*,\\s*|\\s+"));
-          ignoreConflictVersions.put(coordinate, new HashSet<>(ignore));
-        }
-      }
-    }
-    return ! orphansFound;
-  }
-
-  private void collectDirectDependencies() {
-    InterpolatedProperties properties = new InterpolatedProperties();
-    try (InputStream inputStream = new FileInputStream(centralizedVersionsFile);
-         Reader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) {
-      properties.load(reader);
-    } catch (IOException e) {
-      throw new BuildException("Exception reading " + centralizedVersionsFile + ": " + e.toString(), e);
-    }
-    for (Object obj : properties.keySet()) {
-      String coordinate = (String)obj;
-      Matcher matcher = COORDINATE_KEY_PATTERN.matcher(coordinate);
-      if (matcher.matches()) {
-        String org = matcher.group(2);
-        String name = matcher.group(3);
-        String directVersion = properties.getProperty(coordinate);
-        Dependency dependency = new Dependency(org, name, directVersion);
-        directDependencies.put(coordinate, dependency);
-      }
-    }
-  }
-
-  /**
-   * Transitively resolves all dependencies in the given ivy.xml file,
-   * looking for indirect dependencies with versions that conflict
-   * with those of direct dependencies.  Dependency conflict when a
-   * direct dependency's version is older than that of an indirect
-   * dependency with the same /org/name.
-   * 
-   * Returns true if no version conflicts are found and no resolution
-   * errors occurred, false otherwise.
-   */
-  private boolean resolveTransitively(File ivyXmlFile) {
-    boolean success = true;
-
-    ResolveOptions options = new ResolveOptions();
-    options.setDownload(false);           // Download only module descriptors, not artifacts
-    options.setTransitive(true);          // Resolve transitively, if not already specified in the ivy.xml file
-    options.setUseCacheOnly(false);       // Download the internet!
-    options.setOutputReport(false);       // Don't print to the console
-    options.setLog(LogOptions.LOG_QUIET); // Don't log to the console
-    options.setConfs(new String[] {"*"}); // Resolve all configurations
-
-    // Rewrite the ivy.xml, replacing all 'transitive="false"' with 'transitive="true"'
-    // The Ivy API is file-based, so we have to write the result to the filesystem.
-    String moduleName = "unknown";
-    String ivyXmlContent = xmlToString(ivyXmlFile);
-    Matcher matcher = MODULE_NAME_PATTERN.matcher(ivyXmlContent);
-    if (matcher.find()) {
-      moduleName = matcher.group(1);
-    }
-    ivyXmlContent = ivyXmlContent.replaceAll("\\btransitive\\s*=\\s*[\"']false[\"']", "transitive=\"true\"");
-    File transitiveIvyXmlFile = null;
-    try {
-      File buildDir = new File(commonBuildDir, "ivy-transitive-resolve");
-      if ( ! buildDir.exists() && ! buildDir.mkdirs()) {
-        throw new BuildException("Could not create temp directory " + buildDir.getPath());
-      }
-      matcher = MODULE_DIRECTORY_PATTERN.matcher(ivyXmlFile.getCanonicalPath());
-      if ( ! matcher.matches()) {
-        throw new BuildException("Unknown ivy.xml module directory: " + ivyXmlFile.getCanonicalPath());
-      }
-      String moduleDirPrefix = matcher.group(1).replaceAll("[/\\\\]", ".");
-      transitiveIvyXmlFile = new File(buildDir, "transitive." + moduleDirPrefix + ".ivy.xml");
-      try (Writer writer = new OutputStreamWriter(new FileOutputStream(transitiveIvyXmlFile), StandardCharsets.UTF_8)) {
-        writer.write(ivyXmlContent);
-      }
-      ResolveReport resolveReport = ivy.resolve(transitiveIvyXmlFile.toURI().toURL(), options);
-      IvyNodeElement root = IvyNodeElementAdapter.adapt(resolveReport);
-      for (IvyNodeElement directDependency : root.getDependencies()) {
-        String coordinate = "/" + directDependency.getOrganization() + "/" + directDependency.getName();
-        Dependency dependency = directDependencies.get(coordinate);
-        if (null == dependency) {
-          log("ERROR: the following coordinate key does not appear in " 
-              + centralizedVersionsFile.getName() + ": " + coordinate);
-          success = false;
-        } else {
-          dependency.directlyReferenced = true;
-          if (collectConflicts(directDependency, directDependency, moduleName)) {
-            success = false;
-          }
-        }
-      }
-    } catch (ParseException | IOException e) {
-      if (null != transitiveIvyXmlFile) {
-        log("Exception reading " + transitiveIvyXmlFile.getPath() + ": " + e.toString());
-      }
-      success = false;
-    }
-    return success;
-  }
-
-  /**
-   * Recursively finds indirect dependencies that have a version conflict with a direct dependency.
-   * Returns true if one or more conflicts are found, false otherwise
-   */
-  private boolean collectConflicts(IvyNodeElement root, IvyNodeElement parent, String moduleName) {
-    boolean conflicts = false;
-    for (IvyNodeElement child : parent.getDependencies()) {
-      String coordinate = "/" + child.getOrganization() + "/" + child.getName();
-      Dependency dependency = directDependencies.get(coordinate);
-      if (null != dependency) { // Ignore this indirect dependency if it's not also a direct dependency
-        String indirectVersion = child.getRevision();
-        if (isConflict(coordinate, dependency.directVersion, indirectVersion)) {
-          conflicts = true;
-          Set<String> moduleNames = dependency.conflictLocations.get(root);
-          if (null == moduleNames) {
-            moduleNames = new HashSet<>();
-            dependency.conflictLocations.put(root, moduleNames);
-          }
-          moduleNames.add(moduleName);
-        }
-        conflicts |= collectConflicts(root, child, moduleName);
-      }
-    }
-    return conflicts;
-  }
-
-  /**
-   * Copy-pasted from Ivy's 
-   * org.apache.ivy.plugins.latest.LatestRevisionStrategy
-   * with minor modifications
-   */
-  private static final Map<String,Integer> SPECIAL_MEANINGS;
-  static {
-    SPECIAL_MEANINGS = new HashMap<>();
-    SPECIAL_MEANINGS.put("dev", -1);
-    SPECIAL_MEANINGS.put("rc", 1);
-    SPECIAL_MEANINGS.put("final", 2);
-  }
-
-  /**
-   * Copy-pasted from Ivy's 
-   * org.apache.ivy.plugins.latest.LatestRevisionStrategy.MridComparator
-   * with minor modifications
-   */
-  private static class LatestVersionComparator implements Comparator<String> {
-    @Override
-    public int compare(String rev1, String rev2) {
-      rev1 = rev1.replaceAll("([a-zA-Z])(\\d)", "$1.$2");
-      rev1 = rev1.replaceAll("(\\d)([a-zA-Z])", "$1.$2");
-      rev2 = rev2.replaceAll("([a-zA-Z])(\\d)", "$1.$2");
-      rev2 = rev2.replaceAll("(\\d)([a-zA-Z])", "$1.$2");
-
-      String[] parts1 = rev1.split("[-._+]");
-      String[] parts2 = rev2.split("[-._+]");
-
-      int i = 0;
-      for (; i < parts1.length && i < parts2.length; i++) {
-        if (parts1[i].equals(parts2[i])) {
-          continue;
-        }
-        boolean is1Number = isNumber(parts1[i]);
-        boolean is2Number = isNumber(parts2[i]);
-        if (is1Number && !is2Number) {
-          return 1;
-        }
-        if (is2Number && !is1Number) {
-          return -1;
-        }
-        if (is1Number && is2Number) {
-          return Long.valueOf(parts1[i]).compareTo(Long.valueOf(parts2[i]));
-        }
-        // both are strings, we compare them taking into account special meaning
-        Integer sm1 = SPECIAL_MEANINGS.get(parts1[i].toLowerCase(Locale.ROOT));
-        Integer sm2 = SPECIAL_MEANINGS.get(parts2[i].toLowerCase(Locale.ROOT));
-        if (sm1 != null) {
-          sm2 = sm2 == null ? 0 : sm2;
-          return sm1.compareTo(sm2);
-        }
-        if (sm2 != null) {
-          return Integer.valueOf(0).compareTo(sm2);
-        }
-        return parts1[i].compareTo(parts2[i]);
-      }
-      if (i < parts1.length) {
-        return isNumber(parts1[i]) ? 1 : -1;
-      }
-      if (i < parts2.length) {
-        return isNumber(parts2[i]) ? -1 : 1;
-      }
-      return 0;
-    }
-
-    private static final Pattern IS_NUMBER = Pattern.compile("\\d+");
-    private static boolean isNumber(String str) {
-      return IS_NUMBER.matcher(str).matches();
-    }
-  }
-  private static LatestVersionComparator LATEST_VERSION_COMPARATOR = new LatestVersionComparator();
-
-  /**
-   * Returns true if directVersion is less than indirectVersion, and 
-   * coordinate=indirectVersion is not present in ivy-ignore-conflicts.properties. 
-   */
-  private boolean isConflict(String coordinate, String directVersion, String indirectVersion) {
-    boolean isConflict = LATEST_VERSION_COMPARATOR.compare(directVersion, indirectVersion) < 0;
-    if (isConflict) {
-      Set<String> ignoredVersions = ignoreConflictVersions.get(coordinate);
-      if (null != ignoredVersions && ignoredVersions.contains(indirectVersion)) {
-        isConflict = false;
-      }
-    }
-    return isConflict;
-  }
-
-  /**
-   * Returns the number of direct dependencies in conflict with indirect
-   * dependencies.
-   */
-  private int emitConflicts() {
-    int conflicts = 0;
-    StringBuilder builder = new StringBuilder();
-    for (Map.Entry<String,Dependency> directDependency : directDependencies.entrySet()) {
-      String coordinate = directDependency.getKey();
-      Set<Map.Entry<IvyNodeElement,Set<String>>> entrySet
-          = directDependency.getValue().conflictLocations.entrySet();
-      if (entrySet.isEmpty()) {
-        continue;
-      }
-      ++conflicts;
-      Map.Entry<IvyNodeElement,Set<String>> first = entrySet.iterator().next();
-      int notPrinted = entrySet.size() - 1;
-      builder.append("VERSION CONFLICT: transitive dependency in module(s) ");
-      boolean isFirst = true;
-      for (String moduleName : first.getValue()) {
-        if (isFirst) {
-          isFirst = false;
-        } else {
-          builder.append(", ");
-        }
-        builder.append(moduleName);
-      }
-      builder.append(":\n");
-      IvyNodeElement element = first.getKey();
-      builder.append('/').append(element.getOrganization()).append('/').append(element.getName())
-             .append('=').append(element.getRevision()).append('\n');
-      emitConflict(builder, coordinate, first.getKey(), 1);
-        
-      if (notPrinted > 0) {
-        builder.append("... and ").append(notPrinted).append(" more\n");
-      }
-      builder.append("\n");
-    }
-    if (builder.length() > 0) {
-      log(builder.toString());
-    }
-    return conflicts;
-  }
-  
-  private boolean emitConflict(StringBuilder builder, String conflictCoordinate, IvyNodeElement parent, int depth) {
-    for (IvyNodeElement child : parent.getDependencies()) {
-      String indirectCoordinate = "/" + child.getOrganization() + "/" + child.getName();
-      if (conflictCoordinate.equals(indirectCoordinate)) {
-        Dependency dependency = directDependencies.get(conflictCoordinate);
-        String directVersion = dependency.directVersion;
-        if (isConflict(conflictCoordinate, directVersion, child.getRevision())) {
-          for (int i = 0 ; i < depth - 1 ; ++i) {
-            builder.append("    ");
-          }
-          builder.append("+-- ");
-          builder.append(indirectCoordinate).append("=").append(child.getRevision());
-          builder.append(" <<< Conflict (direct=").append(directVersion);
-          builder.append(", latest=").append(dependency.latestVersion).append(")\n");
-          return true;
-        }
-      } else if (hasConflicts(conflictCoordinate, child)) {
-        for (int i = 0 ; i < depth -1 ; ++i) {
-          builder.append("    ");
-        }
-        builder.append("+-- ");
-        builder.append(indirectCoordinate).append("=").append(child.getRevision()).append("\n");
-        if (emitConflict(builder, conflictCoordinate, child, depth + 1)) {
-          return true;
-        }
-      }
-    }
-    return false;
-  }
-  
-  private boolean hasConflicts(String conflictCoordinate, IvyNodeElement parent) {
-    // the element itself will never be in conflict, since its coordinate is different
-    for (IvyNodeElement child : parent.getDependencies()) {
-      String indirectCoordinate = "/" + child.getOrganization() + "/" + child.getName();
-      if (conflictCoordinate.equals(indirectCoordinate)) {
-        Dependency dependency = directDependencies.get(conflictCoordinate);
-        if (isConflict(conflictCoordinate, dependency.directVersion, child.getRevision())) {
-          return true;
-        }
-      } else if (hasConflicts(conflictCoordinate, child)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  private String xmlToString(File ivyXmlFile) {
-    StringWriter writer = new StringWriter();
-    try {
-      StreamSource inputSource = new StreamSource(new FileInputStream(ivyXmlFile.getPath()));
-      Transformer serializer = TransformerFactory.newInstance().newTransformer();
-      serializer.transform(inputSource, new StreamResult(writer));
-    } catch (TransformerException | IOException e) {
-      throw new BuildException("Exception reading " + ivyXmlFile.getPath() + ": " + e.toString(), e);
-    }
-    return writer.toString();
-  }
-
-  private void setupIvy() {
-    IvySettings ivySettings = new IvySettings();
-    try {
-      ivySettings.setVariable("common.build.dir", commonBuildDir.getAbsolutePath());
-      ivySettings.setVariable("ivy.exclude.types", "source|javadoc");
-      ivySettings.setVariable("ivy.resolution-cache.dir", ivyResolutionCacheDir.getAbsolutePath());
-      ivySettings.setVariable("ivy.lock-strategy", ivyLockStrategy);
-      ivySettings.setVariable("ivysettings.xml", getProject().getProperty("ivysettings.xml")); // nested settings file
-      ivySettings.setBaseDir(commonBuildDir);
-      ivySettings.setDefaultConflictManager(new NoConflictManager());
-      ivy = Ivy.newInstance(ivySettings);
-      ivy.configure(topLevelIvySettingsFile);
-    } catch (Exception e) {
-      throw new BuildException("Exception reading " + topLevelIvySettingsFile.getPath() + ": " + e.toString(), e);
-    }
-  }
-
-  /**
-   * Returns true if the "/org/name" coordinate keys in the given
-   * properties file are lexically sorted and are not duplicates.
-   */
-  private boolean verifySortedCoordinatesPropertiesFile(File coordinatePropertiesFile) {
-    log("Checking for lexically sorted non-duplicated '/org/name' keys in: " + coordinatePropertiesFile, verboseLevel);
-    boolean success = true;
-    String line = null;
-    String currentKey = null;
-    String previousKey = null;
-    try (InputStream stream = new FileInputStream(coordinatePropertiesFile);
-         Reader reader = new InputStreamReader(stream, StandardCharsets.ISO_8859_1);
-         BufferedReader bufferedReader = new BufferedReader(reader)) {
-      while (null != (line = readLogicalPropertiesLine(bufferedReader))) {
-        final Matcher keyMatcher = COORDINATE_KEY_PATTERN.matcher(line);
-        if ( ! keyMatcher.lookingAt()) {
-          continue; // Ignore keys that don't look like "/org/name"
-        }
-        currentKey = keyMatcher.group(1);
-        if (null != previousKey) {
-          int comparison = currentKey.compareTo(previousKey);
-          if (0 == comparison) {
-            log("DUPLICATE coordinate key '" + currentKey + "' in " + coordinatePropertiesFile.getName(),
-                Project.MSG_ERR);
-            success = false;
-          } else if (comparison < 0) {
-            log("OUT-OF-ORDER coordinate key '" + currentKey + "' in " + coordinatePropertiesFile.getName(),
-                Project.MSG_ERR);
-            success = false;
-          }
-        }
-        previousKey = currentKey;
-      }
-    } catch (IOException e) {
-      throw new BuildException("Exception reading " + coordinatePropertiesFile.getPath() + ": " + e.toString(), e);
-    }
-    return success;
-  }
-
-  /**
-   * Builds up logical {@link java.util.Properties} lines, composed of one non-blank,
-   * non-comment initial line, either:
-   * 
-   * 1. without a non-escaped trailing slash; or
-   * 2. with a non-escaped trailing slash, followed by
-   *    zero or more lines with a non-escaped trailing slash, followed by
-   *    one or more lines without a non-escaped trailing slash
-   *
-   * All leading non-escaped whitespace and trailing non-escaped whitespace +
-   * non-escaped slash are trimmed from each line before concatenating.
-   * 
-   * After composing the logical line, escaped characters are un-escaped.
-   * 
-   * null is returned if there are no lines left to read. 
-   */
-  private String readLogicalPropertiesLine(BufferedReader reader) throws IOException {
-    final StringBuilder logicalLine = new StringBuilder();
-    String line;
-    do {
-      line = reader.readLine();
-      if (null == line) { 
-        return null;
-      }
-    } while (BLANK_OR_COMMENT_LINE_PATTERN.matcher(line).matches());
-
-    Matcher backslashMatcher = TRAILING_BACKSLASH_PATTERN.matcher(line); 
-    // Check for a non-escaped backslash
-    if (backslashMatcher.find() && 1 == (backslashMatcher.group(1).length() % 2)) {
-      final Matcher firstLineMatcher = TRAILING_WHITESPACE_BACKSLASH_PATTERN.matcher(line);
-      if (firstLineMatcher.matches()) {
-        logicalLine.append(firstLineMatcher.group(1)); // trim trailing backslash and any preceding whitespace
-      }
-      line = reader.readLine();
-      while (null != line
-             && (backslashMatcher = TRAILING_BACKSLASH_PATTERN.matcher(line)).find()
-             && 1 == (backslashMatcher.group(1).length() % 2)) {
-        // Trim leading whitespace, the trailing backslash and any preceding whitespace
-        final Matcher goodStuffMatcher = WHITESPACE_GOODSTUFF_WHITESPACE_BACKSLASH_PATTERN.matcher(line);
-        if (goodStuffMatcher.matches()) {
-          logicalLine.append(goodStuffMatcher.group(1));
-        }
-        line = reader.readLine();
-      }
-      if (null != line) {
-        // line can't have a non-escaped trailing backslash
-        final Matcher leadingWhitespaceMatcher = LEADING_WHITESPACE_PATTERN.matcher(line);
-        if (leadingWhitespaceMatcher.matches()) {
-          line = leadingWhitespaceMatcher.group(1); // trim leading whitespace
-        }
-        logicalLine.append(line);
-      }
-    } else {
-      logicalLine.append(line);
-    }
-    // trim non-escaped leading whitespace
-    final Matcher leadingWhitespaceMatcher = LEADING_WHITESPACE_PATTERN.matcher(logicalLine);
-    final CharSequence leadingWhitespaceStripped = leadingWhitespaceMatcher.matches()
-                                                 ? leadingWhitespaceMatcher.group(1)
-                                                 : logicalLine;
-
-    // unescape all chars in the logical line
-    StringBuilder output = new StringBuilder();
-    final int numChars = leadingWhitespaceStripped.length();
-    for (int pos = 0 ; pos < numChars - 1 ; ++pos) {
-      char ch = leadingWhitespaceStripped.charAt(pos);
-      if (ch == '\\') {
-        ch = leadingWhitespaceStripped.charAt(++pos);
-      }
-      output.append(ch);
-    }
-    if (numChars > 0) {
-      output.append(leadingWhitespaceStripped.charAt(numChars - 1));
-    }
-
-    return output.toString();
-  }
-
-  /**
-   * Check a single ivy.xml file for dependencies' versions in rev="${/org/name}"
-   * format.  Returns false if problems are found, true otherwise.
-   */
-  private boolean checkIvyXmlFile(File ivyXmlFile)
-      throws ParserConfigurationException, SAXException, IOException {
-    log("Scanning: " + ivyXmlFile.getPath(), verboseLevel);
-    SAXParser xmlReader = SAX_PARSER_FACTORY.newSAXParser();
-    DependencyRevChecker revChecker = new DependencyRevChecker(ivyXmlFile); 
-    xmlReader.parse(new InputSource(ivyXmlFile.getAbsolutePath()), revChecker);
-    return ! revChecker.fail;
-  }
-
-  private class DependencyRevChecker extends DefaultHandler {
-    private final File ivyXmlFile;
-    private final Stack<String> tags = new Stack<>();
-    
-    public boolean fail = false;
-
-    public DependencyRevChecker(File ivyXmlFile) {
-      this.ivyXmlFile = ivyXmlFile;
-    }
-
-    @Override
-    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
-      if (localName.equals("dependency") && insideDependenciesTag()) {
-        String org = attributes.getValue("org");
-        boolean foundAllAttributes = true;
-        if (null == org) {
-          log("MISSING 'org' attribute on <dependency> in " + ivyXmlFile.getPath(), Project.MSG_ERR);
-          fail = true;
-          foundAllAttributes = false;
-        }
-        String name = attributes.getValue("name");
-        if (null == name) {
-          log("MISSING 'name' attribute on <dependency> in " + ivyXmlFile.getPath(), Project.MSG_ERR);
-          fail = true;
-          foundAllAttributes = false;
-        }
-        String rev = attributes.getValue("rev");
-        if (null == rev) {
-          log("MISSING 'rev' attribute on <dependency> in " + ivyXmlFile.getPath(), Project.MSG_ERR);
-          fail = true;
-          foundAllAttributes = false;
-        }
-        if (foundAllAttributes) {
-          String coordinateKey = "/" + org + '/' + name;
-          String expectedRev = "${" + coordinateKey + '}';
-          if ( ! rev.equals(expectedRev)) {
-            log("BAD <dependency> 'rev' attribute value '" + rev + "' - expected '" + expectedRev + "'"
-                + " in " + ivyXmlFile.getPath(), Project.MSG_ERR);
-            fail = true;
-          }
-          if ( ! directDependencies.containsKey(coordinateKey)) {
-            log("MISSING key '" + coordinateKey + "' in " + centralizedVersionsFile.getPath(), Project.MSG_ERR);
-            fail = true;
-          }
-        }
-      }
-      tags.push(localName);
-    }
-
-    @Override
-    public void endElement (String uri, String localName, String qName) throws SAXException {
-      tags.pop();
-    }
-
-    private boolean insideDependenciesTag() {
-      return tags.size() == 2 && tags.get(0).equals("ivy-module") && tags.get(1).equals("dependencies");
-    }
-  }
-}
diff --git a/lucene/tools/src/java/org/apache/lucene/validation/LicenseCheckTask.java b/lucene/tools/src/java/org/apache/lucene/validation/LicenseCheckTask.java
deleted file mode 100644
index 96ef01d..0000000
--- a/lucene/tools/src/java/org/apache/lucene/validation/LicenseCheckTask.java
+++ /dev/null
@@ -1,352 +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.lucene.validation;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
-import java.security.DigestInputStream;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-
-import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.Project;
-import org.apache.tools.ant.Task;
-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.resources.FileResource;
-import org.apache.tools.ant.types.resources.Resources;
-import org.apache.tools.ant.util.FileNameMapper;
-
-/**
- * An ANT task that verifies if JAR file have associated <code>LICENSE</code>,
- * <code>NOTICE</code>, and <code>sha1</code> files. 
- */
-public class LicenseCheckTask extends Task {
-
-  public final static String CHECKSUM_TYPE = "sha1";
-  private static final int CHECKSUM_BUFFER_SIZE = 8 * 1024;
-  private static final int CHECKSUM_BYTE_MASK = 0xFF;
-  private static final String FAILURE_MESSAGE = "License check failed. Check the logs.\n"
-      + "If you recently modified ivy-versions.properties or any module's ivy.xml,\n"
-      + "make sure you run \"ant clean-jars jar-checksums\" before running precommit.";
-
-  private Pattern skipRegexChecksum;
-  private boolean skipSnapshotsChecksum;
-  private boolean skipChecksum;
-  
-  /**
-   * All JAR files to check.
-   */
-  private Resources jarResources = new Resources();
-  
-  /**
-   * Directory containing licenses
-   */
-  private File licenseDirectory;
-
-  /**
-   * License file mapper.
-   */
-  private FileNameMapper licenseMapper;
-
-  /**
-   * A logging level associated with verbose logging.
-   */
-  private int verboseLevel = Project.MSG_VERBOSE;
-  
-  /**
-   * Failure flag.
-   */
-  private boolean failures;
-
-  /**
-   * Adds a set of JAR resources to check.
-   */
-  public void add(ResourceCollection rc) {
-    jarResources.add(rc);
-  }
-  
-  /**
-   * Adds a license mapper.
-   */
-  public void addConfiguredLicenseMapper(Mapper mapper) {
-    if (licenseMapper != null) {
-      throw new BuildException("Only one license mapper is allowed.");
-    }
-    this.licenseMapper = mapper.getImplementation();
-  }
-
-  public void setVerbose(boolean verbose) {
-    verboseLevel = (verbose ? Project.MSG_INFO : Project.MSG_VERBOSE);
-  }
-  
-  public void setLicenseDirectory(File file) {
-    licenseDirectory = file;
-  }
-  
-  public void setSkipSnapshotsChecksum(boolean skipSnapshotsChecksum) {
-    this.skipSnapshotsChecksum = skipSnapshotsChecksum;
-  }
-  
-  public void setSkipChecksum(boolean skipChecksum) {
-    this.skipChecksum = skipChecksum;
-  }
-
-  public void setSkipRegexChecksum(String skipRegexChecksum) {
-    try {
-      if (skipRegexChecksum != null && skipRegexChecksum.length() > 0) {
-        this.skipRegexChecksum = Pattern.compile(skipRegexChecksum);
-      }
-    } catch (PatternSyntaxException e) {
-      throw new BuildException("Unable to compile skipRegexChecksum pattern.  Reason: "
-          + e.getMessage() + " " + skipRegexChecksum, e);
-    }
-  }
-
-  /**
-   * Execute the task.
-   */
-  @Override
-  public void execute() throws BuildException {
-    if (licenseMapper == null) {
-      throw new BuildException("Expected an embedded <licenseMapper>.");
-    }
-
-    if (skipChecksum) {
-      log("Skipping checksum verification for dependencies", Project.MSG_INFO);
-    } else {
-      if (skipSnapshotsChecksum) {
-        log("Skipping checksum for SNAPSHOT dependencies", Project.MSG_INFO);
-      }
-
-      if (skipRegexChecksum != null) {
-        log("Skipping checksum for dependencies matching regex: " + skipRegexChecksum.pattern(),
-            Project.MSG_INFO);
-      }
-    }
-
-    jarResources.setProject(getProject());
-    processJars();
-
-    if (failures) {
-      throw new BuildException(FAILURE_MESSAGE);
-    }
-  }
-
-  /**
-   * Process all JARs.
-   */
-  private void processJars() {
-    log("Starting scan.", verboseLevel);
-    long start = System.currentTimeMillis();
-
-    @SuppressWarnings("unchecked")
-    Iterator<Resource> iter = (Iterator<Resource>) jarResources.iterator();
-    int checked = 0;
-    int errors = 0;
-    while (iter.hasNext()) {
-      final Resource r = iter.next();
-      if (!r.isExists()) { 
-        throw new BuildException("JAR resource does not exist: " + r.getName());
-      }
-      if (!(r instanceof FileResource)) {
-        throw new BuildException("Only filesystem resource are supported: " + r.getName()
-            + ", was: " + r.getClass().getName());
-      }
-
-      File jarFile = ((FileResource) r).getFile();
-      if (! checkJarFile(jarFile) ) {
-        errors++;
-      }
-      checked++;
-    }
-
-    log(String.format(Locale.ROOT, 
-        "Scanned %d JAR file(s) for licenses (in %.2fs.), %d error(s).",
-        checked, (System.currentTimeMillis() - start) / 1000.0, errors),
-        errors > 0 ? Project.MSG_ERR : Project.MSG_INFO);
-  }
-
-  /**
-   * Check a single JAR file.
-   */
-  private boolean checkJarFile(File jarFile) {
-    log("Scanning: " + jarFile.getPath(), verboseLevel);
-    
-    if (!skipChecksum) {
-      boolean skipDueToSnapshot = skipSnapshotsChecksum && jarFile.getName().contains("-SNAPSHOT");
-      if (!skipDueToSnapshot && !matchesRegexChecksum(jarFile, skipRegexChecksum)) {
-        // validate the jar matches against our expected hash
-        final File checksumFile = new File(licenseDirectory, jarFile.getName()
-            + "." + CHECKSUM_TYPE);
-        if (!(checksumFile.exists() && checksumFile.canRead())) {
-          log("MISSING " + CHECKSUM_TYPE + " checksum file for: "
-              + jarFile.getPath(), Project.MSG_ERR);
-          log("EXPECTED " + CHECKSUM_TYPE + " checksum file : "
-              + checksumFile.getPath(), Project.MSG_ERR);
-          this.failures = true;
-          return false;
-        } else {
-          final String expectedChecksum = readChecksumFile(checksumFile);
-          try {
-            final MessageDigest md = MessageDigest.getInstance(CHECKSUM_TYPE);
-            byte[] buf = new byte[CHECKSUM_BUFFER_SIZE];
-            try {
-              FileInputStream fis = new FileInputStream(jarFile);
-              try {
-                DigestInputStream dis = new DigestInputStream(fis, md);
-                try {
-                  while (dis.read(buf, 0, CHECKSUM_BUFFER_SIZE) != -1) {
-                    // NOOP
-                  }
-                } finally {
-                  dis.close();
-                }
-              } finally {
-                fis.close();
-              }
-            } catch (IOException ioe) {
-              throw new BuildException("IO error computing checksum of file: "
-                  + jarFile, ioe);
-            }
-            final byte[] checksumBytes = md.digest();
-            final String checksum = createChecksumString(checksumBytes);
-            if (!checksum.equals(expectedChecksum)) {
-              log("CHECKSUM FAILED for " + jarFile.getPath() + " (expected: \""
-                  + expectedChecksum + "\" was: \"" + checksum + "\")",
-                  Project.MSG_ERR);
-              this.failures = true;
-              return false;
-            }
-            
-          } catch (NoSuchAlgorithmException ae) {
-            throw new BuildException("Digest type " + CHECKSUM_TYPE
-                + " not supported by your JVM", ae);
-          }
-        }
-      } else if (skipDueToSnapshot) {
-        log("Skipping jar because it is a SNAPSHOT : "
-            + jarFile.getAbsolutePath(), Project.MSG_INFO);
-      } else {
-        log("Skipping jar because it matches regex pattern: "
-            + jarFile.getAbsolutePath() + " pattern: " + skipRegexChecksum.pattern(), Project.MSG_INFO);
-      }
-    }
-    
-    // Get the expected license path base from the mapper and search for license files.
-    Map<File, LicenseType> foundLicenses = new LinkedHashMap<>();
-    List<File> expectedLocations = new ArrayList<>();
-outer:
-    for (String mappedPath : licenseMapper.mapFileName(jarFile.getName())) {
-      for (LicenseType licenseType : LicenseType.values()) {
-        File licensePath = new File(licenseDirectory, mappedPath + licenseType.licenseFileSuffix());
-        if (licensePath.exists()) {
-          foundLicenses.put(licensePath, licenseType);
-          log(" FOUND " + licenseType.name() + " license at " + licensePath.getPath(), 
-              verboseLevel);
-          // We could continue scanning here to detect duplicate associations?
-          break outer;
-        } else {
-          expectedLocations.add(licensePath);
-        }
-      }
-    }
-
-    // Check for NOTICE files.
-    for (Map.Entry<File, LicenseType> e : foundLicenses.entrySet()) {
-      LicenseType license = e.getValue();
-      String licensePath = e.getKey().getName();
-      String baseName = licensePath.substring(
-          0, licensePath.length() - license.licenseFileSuffix().length());
-      File noticeFile = new File(licenseDirectory, baseName + license.noticeFileSuffix());
-
-      if (noticeFile.exists()) {
-        log(" FOUND NOTICE file at " + noticeFile.getAbsolutePath(), verboseLevel);
-      } else {
-        if (license.isNoticeRequired()) {
-            this.failures = true;
-            log("MISSING NOTICE for the license file:\n  "
-                + licensePath + "\n  Expected location below:\n  "
-                + noticeFile.getAbsolutePath(), Project.MSG_ERR);
-        }
-      }
-    }
-
-    // In case there is something missing, complain.
-    if (foundLicenses.isEmpty()) {
-      this.failures = true;
-      StringBuilder message = new StringBuilder();
-      message.append("MISSING LICENSE for the following file:\n  ").append(jarFile.getAbsolutePath()).append("\n  Expected locations below:\n");
-      for (File location : expectedLocations) {
-        message.append("  => ").append(location.getAbsolutePath()).append("\n");
-      }
-      log(message.toString(), Project.MSG_ERR);
-      return false;
-    }
-
-    return true;
-  }
-
-  private static final String createChecksumString(byte[] digest) {
-    StringBuilder checksum = new StringBuilder();
-    for (int i = 0; i < digest.length; i++) {
-      checksum.append(String.format(Locale.ROOT, "%02x", 
-                                    CHECKSUM_BYTE_MASK & digest[i]));
-    }
-    return checksum.toString();
-  }
-  private static final String readChecksumFile(File f) {
-    BufferedReader reader = null;
-    try {
-      reader = new BufferedReader(new InputStreamReader
-                                  (new FileInputStream(f), StandardCharsets.UTF_8));
-      try {
-        String checksum = reader.readLine();
-        if (null == checksum || 0 == checksum.length()) {
-          throw new BuildException("Failed to find checksum in file: " + f);
-        }
-        return checksum;
-      } finally {
-        reader.close();
-      }
-    } catch (IOException e) {
-      throw new BuildException("IO error reading checksum file: " + f, e);
-    }
-  }
-
-  private static final boolean matchesRegexChecksum(File jarFile, Pattern skipRegexChecksum) {
-    if (skipRegexChecksum == null) {
-      return false;
-    }
-    Matcher m = skipRegexChecksum.matcher(jarFile.getName());
-    return m.matches();
-  }
-}
diff --git a/lucene/tools/src/java/org/apache/lucene/validation/LicenseType.java b/lucene/tools/src/java/org/apache/lucene/validation/LicenseType.java
deleted file mode 100644
index 2359382..0000000
--- a/lucene/tools/src/java/org/apache/lucene/validation/LicenseType.java
+++ /dev/null
@@ -1,75 +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.lucene.validation;
-
-
-/**
- * A list of accepted licenses.  See also http://www.apache.org/legal/3party.html
- *
- **/
-public enum LicenseType {
-  ASL("Apache Software License 2.0", true),
-  BSD("Berkeley Software Distribution", true),
-  BSD_LIKE("BSD like license", true),//BSD like just means someone has taken the BSD license and put in their name, copyright, or it's a very similar license.
-  CDDL("Common Development and Distribution License", false),
-  CPL("Common Public License", true),
-  EPL("Eclipse Public License Version 1.0", false),
-  MIT("Massachusetts Institute of Tech. License", false),
-  MPL("Mozilla Public License", false), //NOT SURE on the required notice
-  PD("Public Domain", false),
-  //SUNBCLA("Sun Binary Code License Agreement"),
-  SUN("Sun Open Source License", false),
-  COMPOUND("Compound license (see NOTICE).", true),
-  FAKE("FAKE license - not needed", false);
-
-  private String display;
-  private boolean noticeRequired;
-
-  LicenseType(String display, boolean noticeRequired) {
-    this.display = display;
-    this.noticeRequired = noticeRequired;
-  }
-
-  public boolean isNoticeRequired() {
-    return noticeRequired;
-  }
-
-  public String getDisplay() {
-    return display;
-  }
-
-  public String toString() {
-    return "LicenseType{" +
-            "display='" + display + '\'' +
-            '}';
-  }
-
-  /**
-   * Expected license file suffix for a given license type.
-   */
-  public String licenseFileSuffix() {
-    return "-LICENSE-" + this.name() + ".txt";
-  }
-
-  /**
-   * Expected notice file suffix for a given license type.
-   */
-  public String noticeFileSuffix() {
-    return "-NOTICE.txt";
-  }
-}
-
diff --git a/lucene/tools/src/java/org/apache/lucene/validation/ivyde/IvyNodeElement.java b/lucene/tools/src/java/org/apache/lucene/validation/ivyde/IvyNodeElement.java
deleted file mode 100644
index 287527e..0000000
--- a/lucene/tools/src/java/org/apache/lucene/validation/ivyde/IvyNodeElement.java
+++ /dev/null
@@ -1,178 +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.lucene.validation.ivyde;
-
-import org.apache.ivy.core.module.id.ModuleRevisionId;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-
-/**
- * Assists in the further separation of concerns between the view and the Ivy resolve report. The view looks at the
- * IvyNode in a unique way that can lead to expensive operations if we do not achieve this separation.
- * 
- * This class is copied from org/apache/ivyde/eclipse/resolvevisualizer/model/IvyNodeElement.java at 
- * https://svn.apache.org/repos/asf/ant/ivy/ivyde/trunk/org.apache.ivyde.eclipse.resolvevisualizer/src/
- *
- * Changes include: uncommenting generics and converting to diamond operators where appropriate;
- * removing unnecessary casts; removing javadoc tags with no description; and adding a hashCode() implementation.
- */
-public class IvyNodeElement {
-  private ModuleRevisionId moduleRevisionId;
-  private boolean evicted = false;
-  private int depth = Integer.MAX_VALUE / 10;
-  private Collection<IvyNodeElement> dependencies = new HashSet<>();
-  private Collection<IvyNodeElement> callers = new HashSet<>();
-  private Collection<IvyNodeElement> conflicts = new HashSet<>();
-
-  /**
-   * The caller configurations that caused this node to be reached in the resolution, grouped by caller.
-   */
-  private Map<IvyNodeElement,String[]>callerConfigurationMap = new HashMap<>();
-
-  /**
-   * We try to avoid building the list of this nodes deep dependencies by storing them in this cache by depth level.
-   */
-  private IvyNodeElement[] deepDependencyCache;
-  
-  @Override
-  public boolean equals(Object obj) {
-    if (obj instanceof IvyNodeElement) {
-      IvyNodeElement elem = (IvyNodeElement) obj;
-      if (elem.getOrganization().equals(getOrganization()) && elem.getName().equals(getName())
-          && elem.getRevision().equals(getRevision()))
-        return true;
-    }
-    return false;
-  }
-  
-  @Override
-  public int hashCode() {
-    int result = 1;
-    result = result * 31 + (null == getOrganization() ? 0 : getOrganization().hashCode());
-    result = result * 31 + (null == getName() ? 0 : getName().hashCode());
-    result = result * 31 + (null == getRevision() ? 0 : getRevision().hashCode());
-    return result;
-  }
-
-  public IvyNodeElement[] getDependencies() {
-    return dependencies.toArray(new IvyNodeElement[dependencies.size()]);
-  }
-
-  /**
-   * Recursive dependency retrieval
-   *
-   * @return The array of nodes that represents a node's immediate and transitive dependencies down to an arbitrary
-   *         depth.
-   */
-  public IvyNodeElement[] getDeepDependencies() {
-    if (deepDependencyCache == null) {
-      Collection<IvyNodeElement> deepDependencies = getDeepDependencies(this);
-      deepDependencyCache = deepDependencies.toArray(new IvyNodeElement[deepDependencies.size()]);
-    }
-    return deepDependencyCache;
-  }
-
-  /**
-   * Recursive dependency retrieval
-   */
-  private Collection<IvyNodeElement> getDeepDependencies(IvyNodeElement node) {
-    Collection<IvyNodeElement> deepDependencies = new HashSet<>();
-    deepDependencies.add(node);
-
-    IvyNodeElement[] directDependencies = node.getDependencies();
-    for (int i = 0; i < directDependencies.length; i++) {
-      deepDependencies.addAll(getDeepDependencies(directDependencies[i]));
-    }
-
-    return deepDependencies;
-  }
-
-  /**
-   * @return An array of configurations by which this module was resolved
-   */
-  public String[] getCallerConfigurations(IvyNodeElement caller) {
-    return callerConfigurationMap.get(caller);
-  }
-
-  public void setCallerConfigurations(IvyNodeElement caller, String[] configurations) {
-    callerConfigurationMap.put(caller, configurations);
-  }
-
-  public String getOrganization() {
-    return moduleRevisionId.getOrganisation();
-  }
-
-  public String getName() {
-    return moduleRevisionId.getName();
-  }
-
-  public String getRevision() {
-    return moduleRevisionId.getRevision();
-  }
-
-  public boolean isEvicted() {
-    return evicted;
-  }
-
-  public void setEvicted(boolean evicted) {
-    this.evicted = evicted;
-  }
-
-  public int getDepth() {
-    return depth;
-  }
-
-  /**
-   * Set this node's depth and recursively update the node's children to relative to the new value.
-   */
-  public void setDepth(int depth) {
-    this.depth = depth;
-    for (Iterator<IvyNodeElement> iter = dependencies.iterator(); iter.hasNext();) {
-      IvyNodeElement dependency = iter.next();
-      dependency.setDepth(depth + 1);
-    }
-  }
-
-  public IvyNodeElement[] getConflicts() {
-    return conflicts.toArray(new IvyNodeElement[conflicts.size()]);
-  }
-
-  public void setConflicts(Collection<IvyNodeElement> conflicts) {
-    this.conflicts = conflicts;
-  }
-
-  public ModuleRevisionId getModuleRevisionId() {
-    return moduleRevisionId;
-  }
-
-  public void setModuleRevisionId(ModuleRevisionId moduleRevisionId) {
-    this.moduleRevisionId = moduleRevisionId;
-  }
-
-  public void addCaller(IvyNodeElement caller) {
-    callers.add(caller);
-    caller.dependencies.add(this);
-  }
-
-  public IvyNodeElement[] getCallers() {
-    return callers.toArray(new IvyNodeElement[callers.size()]);
-  }
-}
\ No newline at end of file
diff --git a/lucene/tools/src/java/org/apache/lucene/validation/ivyde/IvyNodeElementAdapter.java b/lucene/tools/src/java/org/apache/lucene/validation/ivyde/IvyNodeElementAdapter.java
deleted file mode 100644
index c754dd4..0000000
--- a/lucene/tools/src/java/org/apache/lucene/validation/ivyde/IvyNodeElementAdapter.java
+++ /dev/null
@@ -1,135 +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.lucene.validation.ivyde;
-
-import org.apache.ivy.core.module.id.ModuleId;
-import org.apache.ivy.core.module.id.ModuleRevisionId;
-import org.apache.ivy.core.report.ResolveReport;
-import org.apache.ivy.core.resolve.IvyNode;
-import org.apache.ivy.core.resolve.IvyNodeCallers;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-/**
- * This class is copied from org/apache/ivyde/eclipse/resolvevisualizer/model/IvyNodeElementAdapter.java at 
- * https://svn.apache.org/repos/asf/ant/ivy/ivyde/trunk/org.apache.ivyde.eclipse.resolvevisualizer/src/
- * 
- * Changes include: uncommenting generics and converting to diamond operators where appropriate;
- * removing unnecessary casts; and removing javadoc tags with no description.
- */
-public class IvyNodeElementAdapter {
-  /**
-   * Adapt all dependencies and evictions from the ResolveReport.
-   * @return the root node adapted from the ResolveReport
-   */
-  public static IvyNodeElement adapt(ResolveReport report) {
-    Map<ModuleRevisionId,IvyNodeElement> resolvedNodes = new HashMap<>();
-
-    IvyNodeElement root = new IvyNodeElement();
-    root.setModuleRevisionId(report.getModuleDescriptor().getModuleRevisionId());
-    resolvedNodes.put(report.getModuleDescriptor().getModuleRevisionId(), root);
-
-    @SuppressWarnings("unchecked") List<IvyNode> dependencies = report.getDependencies();
-
-    // First pass - build the map of resolved nodes by revision id
-    for (Iterator<IvyNode> iter = dependencies.iterator(); iter.hasNext();) {
-      IvyNode node = iter.next();
-      if (node.getAllEvictingNodes() != null) {
-        // Nodes that are evicted as a result of conf inheritance still appear
-        // as dependencies, but with eviction data. They also appear as evictions.
-        // We map them as evictions rather than dependencies.
-        continue;
-      }
-      IvyNodeElement nodeElement = new IvyNodeElement();
-      nodeElement.setModuleRevisionId(node.getResolvedId());
-      resolvedNodes.put(node.getResolvedId(), nodeElement);
-    }
-
-    // Second pass - establish relationships between the resolved nodes
-    for (Iterator<IvyNode> iter = dependencies.iterator(); iter.hasNext();) {
-      IvyNode node = iter.next();
-      if (node.getAllEvictingNodes() != null) {
-        continue; // see note above
-      }
-
-      IvyNodeElement nodeElement = resolvedNodes.get(node.getResolvedId());
-      IvyNodeCallers.Caller[] callers = node.getAllRealCallers();
-      for (int i = 0; i < callers.length; i++) {
-        IvyNodeElement caller = resolvedNodes.get(callers[i].getModuleRevisionId());
-        if (caller != null) {
-          nodeElement.addCaller(caller);
-          nodeElement.setCallerConfigurations(caller, callers[i].getCallerConfigurations());
-        }
-      }
-    }
-
-    IvyNode[] evictions = report.getEvictedNodes();
-    for (int i = 0; i < evictions.length; i++) {
-      IvyNode eviction = evictions[i];
-      IvyNodeElement evictionElement = new IvyNodeElement();
-      evictionElement.setModuleRevisionId(eviction.getResolvedId());
-      evictionElement.setEvicted(true);
-
-      IvyNodeCallers.Caller[] callers = eviction.getAllCallers();
-      for (int j = 0; j < callers.length; j++) {
-        IvyNodeElement caller = resolvedNodes.get(callers[j].getModuleRevisionId());
-        if (caller != null) {
-          evictionElement.addCaller(caller);
-          evictionElement.setCallerConfigurations(caller, callers[j].getCallerConfigurations());
-        }
-      }
-    }
-
-    // Recursively set depth starting at root
-    root.setDepth(0);
-    findConflictsBeneathNode(root);
-
-    return root;
-  }
-
-  /**
-   * Derives configuration conflicts that exist between node and all of its descendant dependencies.
-   */
-  private static void findConflictsBeneathNode(IvyNodeElement node) {
-    // Derive conflicts
-    Map<ModuleId,Collection<IvyNodeElement>> moduleRevisionMap = new HashMap<>();
-    IvyNodeElement[] deepDependencies = node.getDeepDependencies();
-    for (int i = 0; i < deepDependencies.length; i++) {
-      if (deepDependencies[i].isEvicted())
-        continue;
-
-      ModuleId moduleId = deepDependencies[i].getModuleRevisionId().getModuleId();
-      if (moduleRevisionMap.containsKey(moduleId)) {
-        Collection<IvyNodeElement> conflicts = moduleRevisionMap.get(moduleId);
-        conflicts.add(deepDependencies[i]);
-        for (Iterator<IvyNodeElement> iter = conflicts.iterator(); iter.hasNext();) {
-          IvyNodeElement conflict = iter.next();
-          conflict.setConflicts(conflicts);
-        }
-      } else {
-        List<IvyNodeElement> immutableMatchingSet = Arrays.asList(deepDependencies[i]);
-        moduleRevisionMap.put(moduleId, new HashSet<>(immutableMatchingSet));
-      }
-    }
-  }
-}
\ No newline at end of file
diff --git a/solr/contrib/prometheus-exporter/build.gradle b/solr/contrib/prometheus-exporter/build.gradle
index 13a9748..6ff390f 100644
--- a/solr/contrib/prometheus-exporter/build.gradle
+++ b/solr/contrib/prometheus-exporter/build.gradle
@@ -37,11 +37,3 @@ dependencies {
 
   testImplementation project(':solr:test-framework')
 }
-
-// Add two folders to default packaging.
-assemblePackaging {
-  from(projectDir, {
-    include "bin/**"
-    include "conf/**"
-  })
-}
\ No newline at end of file