You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ma...@apache.org on 2019/10/23 16:59:39 UTC

[lucene-solr] branch jira/SOLR-13452_gradle_7 updated: SOLR-13452: A variety of clean up work

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

markrmiller pushed a commit to branch jira/SOLR-13452_gradle_7
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git


The following commit(s) were added to refs/heads/jira/SOLR-13452_gradle_7 by this push:
     new c696861  SOLR-13452: A variety of clean up work
c696861 is described below

commit c69686114abb04066ec782e41ffd50d17503f688
Author: Mark Miller <ma...@apache.org>
AuthorDate: Wed Oct 23 11:51:45 2019 -0500

    SOLR-13452: A variety of clean up work
    
    * We are incorrectly overriding our projects default directory based name - this really had the project in a whacky state.
    * Fix tests, we could no longer read classes from other projects.
    * Move build and build-eclipse to the root level instead of per project, making them easier to navigate and treat specially.
    * Look for user property overrides in user.properties in both the project root dir and the user home directory.
    * Some other minor fixes and cleanup.
---
 .gitignore                                         |   3 +-
 build.gradle                                       | 449 +++++++++++----------
 .../build-wdocker-test/setup-script-for-test.sh    |   4 +-
 buildSrc/build-wdocker-test/start.sh               |   4 +-
 buildSrc/build-wdocker-test/test-rat-sources.sh    |  29 +-
 buildSrc/build.gradle                              |   8 +-
 buildSrc/common/build-help.gradle                  |   4 +-
 buildSrc/common/configure-ext.gradle               |  71 ++--
 buildSrc/common/configure-test.gradle              |  49 ++-
 buildSrc/ide/eclipse.gradle                        | 114 +++---
 buildSrc/src/buildTest/java/TestChecks.java        |  48 ++-
 .../org/apache/lucene/gradle/TopHints.groovy       |   2 +-
 .../apache/lucene/gradle/checks/RatSources.groovy  |   3 +-
 .../apache/lucene/gradle/deps/MissingDeps.groovy   |  14 +-
 .../org/apache/lucene/gradle/LicenseCheckTask.java |  16 +
 lucene/analysis/icu/build.gradle                   |   2 +-
 lucene/analysis/kuromoji/build.gradle              |   2 +-
 lucene/analysis/morfologik/build.gradle            |   2 +-
 lucene/analysis/nori/build.gradle                  |   4 +-
 lucene/analysis/opennlp/build.gradle               |   2 +-
 lucene/analysis/phonetic/build.gradle              |   2 +-
 lucene/analysis/smartcn/build.gradle               |   2 +-
 lucene/analysis/stempel/build.gradle               |   2 +-
 lucene/benchmark/build.gradle                      |   2 +-
 lucene/build.gradle                                |   2 +
 lucene/classification/build.gradle                 |   2 +-
 lucene/demo/build.gradle                           |   2 +-
 lucene/expressions/build.gradle                    |   6 +-
 lucene/highlighter/build.gradle                    |   2 +-
 lucene/luke/build.gradle                           |   2 +-
 lucene/monitor/build.gradle                        |   2 +-
 lucene/suggest/build.gradle                        |   2 +-
 lucene/test-framework/build.gradle                 |   3 +-
 settings.gradle                                    | 211 +++++-----
 solr/build.gradle                                  |   4 +-
 solr/contrib/analysis-extras/build.gradle          |  14 +-
 solr/contrib/analytics/build.gradle                |   2 +-
 solr/contrib/clustering/build.gradle               |   2 +-
 solr/contrib/dataimporthandler-extras/build.gradle |  10 +-
 solr/contrib/dataimporthandler/build.gradle        |   2 +-
 solr/contrib/extraction/build.gradle               |   2 +-
 solr/contrib/langid/build.gradle                   |   4 +-
 solr/contrib/ltr/build.gradle                      |   3 +-
 solr/contrib/prometheus-exporter/build.gradle      |   2 +-
 solr/contrib/velocity/build.gradle                 |   2 +-
 solr/core/build.gradle                             |  18 +-
 solr/server/build.gradle                           |  43 +-
 solr/solrj/build.gradle                            |   4 +-
 solr/test-framework/build.gradle                   |   4 +-
 versions.lock                                      |   2 +-
 50 files changed, 652 insertions(+), 538 deletions(-)

diff --git a/.gitignore b/.gitignore
index 28b854a..42862cf1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,7 @@ eclipse-build
 /maven-build
 /classes
 build
+build-eclipse
 /idea-build
 dist
 lib
@@ -23,7 +24,6 @@ lucene/**/*.iml
 .caches
 .out
 /prj.el
-bin
 /bin.*
 pom.xml
 /nbproject
@@ -34,3 +34,4 @@ __pycache__
 .DS_Store
 .gradle
 derby.log
+user.properties
diff --git a/build.gradle b/build.gradle
index bcc2010..dea9a5c 100644
--- a/build.gradle
+++ b/build.gradle
@@ -36,221 +36,195 @@ plugins {
 }
 
 // TOC
-// -> defs and all project ext config
-// -> lucene-solr all module config
-// -> lucene-solr sub module config
-// -> lucene-solr root project config
-// -> all projects config
-// ->   lucene-solr IDE config
-// ->   dependencies
-// -> other config
+// -> Definitions
+// -> Root project config
+// -> All projects config
+// -> Subprojects config
+// -> Other config
 
 
-// *** defs and all project ext config
+// ### -> defs and all project ext config
 
 buildDir = file("build")
 
-// define lucene-solr project lists
-def luceneSolrProjects = allprojects
-def luceneSolrSubProjects = subprojects
+File userHomeConfigFile = new File(System.getProperty("user.home") + '/user.properties')
+if (userHomeConfigFile.exists()) {
+  println 'Found user home user.gradle, loading ...'
+  Properties props = new Properties()
+  userHomeConfigFile.withInputStream { props.load(it) }
+
+  for (java.util.Map$Entry<Map<String,String>> entry : props.entrySet()) {
+    ext.set(entry.getKey(), entry.getValue())
+  }
+} else {
+  println 'not user home user.gradle ' + userHomeConfigFile
+}
 
-def rootProjectDir = project.rootProject.projectDir;
 
 // we add some custom ext methods here, including mfile
-apply from: file("${rootProjectDir}/buildSrc/common/configure-ext.gradle")
+apply from: file("${rootDir}/buildSrc/common/configure-ext.gradle")
 
 // build help tasks
-apply from: mfile(rootProjectDir, 'buildSrc/common/build-help.gradle')
+apply from: mfile(rootDir, 'buildSrc/common/build-help.gradle')
 
+// setup repositories
+apply from: mfile(rootDir, 'buildSrc/common/configure-repositories.gradle')
+
+
+// ### -> lucene-solr root project config
+
+// TODO: enable the modified files checking only for jenkins runs! sysprop?
+tasks.create('checkWorkingCopy', CheckWorkingCopy, false)
 
-// *** lucene-solr all module config - configure all lucene-solr projects, including root project
-configure(luceneSolrProjects) {
-    buildDir = file("build")
-    
-    // setup repositories
-    apply from: mfile(rootProjectDir, 'buildSrc/common/configure-repositories.gradle')
 
-    project.plugins.apply(ForbiddenApisPluginWrapper)
+task testTimes(type: TopHints) {
+  group = 'Tests'
+  description = "Show the slowest tests (averages)."
 }
 
-configure(luceneSolrProjects) {
-  project.evaluationDependsOn(':buildSrc')
-  
-  task ratSources(type: RatSources) {
-      group = 'Verification'
-      description = "Checks source files for proper license headers."
-      excludes = [
-        '**/TODO',
-        '**/*.txt,',
-        '**/*.iml'
-      ]
-      // TODO: even if we don't have a check task, we want to run RAT - on our root files for example
-      if (project.hasProperty('check')) {
-        check.dependsOn ratSources
-      }
-  }
+task pristineClean(type: PristineClean) {}
+
+task defaultUserConfig(type: SetDefaultUserConfig) {
+  group = 'Build Setup'
+  description = "Sets recommended starting build property values in ~/.gradle/gradle.properties. Use --agressive for better build performance. WARNING! This WILL modify your gradle.properties file."
 }
 
-// *** lucene-solr sub module config - configure all lucene-solr modules (excludes the root project)
-configure(luceneSolrSubProjects) {
+ext.testsResults = [] // test result summaries
+gradle.buildFinished {
+  def allResults = ext.testsResults
 
-// TODO: prob wont go here    
-//  task checkMissingJavaDocs {
-//    group = 'Verification'
-//    description = "Checks for missing JavaDocs."
+  if (!allResults.isEmpty()) {
+    printResults allResults
+  }
+}
+
+// ### -> All project config
+configure(allprojects) {
+//  File userProjectConfigFile = project.rootProject.file('user.gradle')
+//  if (userProjectConfigFile.exists()) {
+//    println 'Found user project user.gradle, applying ...'
+//    project.apply from: userProjectConfigFile
+//  } else {
 //    
-//    doLast {
-//      project.exec {
-//        workingDir project.projectDir.getAbsolutePath()
-//        executable "${python_exe}"
-//        args = [
-//          '-B',
-//          rootProjectDir.getAbsolutePath() + '/dev-tools/scripts/checkJavaDocs.py',
-//          project.projectDir.getAbsolutePath(),
-//          'class'
-//        ]
-//      }
-//    }
 //  }
+//  
+//  File userHomeConfigFile = new File(System.getProperty("user.home") + '/user.gradle')
+//  if (userHomeConfigFile.exists()) {
+//    println 'Found user home user.gradle, applying ...'
+//    project.apply from: userHomeConfigFile
+//  } else {
+//    println 'not user home user.gradle ' + userHomeConfigFile
+//  }
+
+  
   
-  // TODO: check.dependsOn checkMissingJavaDocs
+  // we apply eclipse to all projects - we want our formatting if you edit build.gradle in a non java project
+  // as well as the ability to configure other things for all projects
+  apply plugin: 'eclipse'
+  project.afterEvaluate{
+    project.apply from: mfile(rootDir, 'buildSrc/ide/eclipse.gradle')
+  }
+}
+
+// ### -> Subprojects config
+configure(subprojects) {
+
+  buildDir = rootProject.mfile('build/' + getTopLvlProject().name, project.name)
+
+  // setup repositories
+  apply from: mfile(rootDir, 'buildSrc/common/configure-repositories.gradle')
+
+  apply plugin: 'idea'
+
+  plugins.withType(JavaPlugin) {
+    project.apply from: mfile(rootDir, 'buildSrc/ide/idea.gradle')
+  }
+
+  task ratSources(type: RatSources) {
+    group = 'Verification'
+    description = "Checks source files for proper license headers."
+    excludes = [
+      '**/TODO',
+      '**/*.txt,',
+      '**/*.iml'
+    ]
+    // TODO: even if we don't have a check task, we want to run RAT - on our root files for example
+    if (project.hasProperty('check')) {
+      check.dependsOn ratSources
+    }
+  }
   
+  task checkSourcePatterns(type: CheckSourcePatterns) {
+    group = 'Verification'
+    description = "Checks source files for project violations."
+    baseDir = projectDir
+    check.dependsOn checkSourcePatterns
+  }
+
+  plugins.apply(ForbiddenApisPluginWrapper)
+
   task depInsight(type: DepInsightReportTask) {
     group = 'Help'
     description = "An alternate to dependencyInsight that works across projects so that you can run it from the root directory or aggregate projects eg lucene, solr, solr-contrib"
   }
-  
+
   configurations {
     sourceJarOutput
   }
-    
-  plugins.withType(JavaPlugin) {
+  
+  
+  File jdepsReportDir = mfile(project.buildDir, 'jdepsreport')
 
-    task checkSourcePatterns(type: CheckSourcePatterns) {
-      group = 'Verification'
-      description = "Checks source files for project violations."
-      baseDir = projectDir
-      check.dependsOn checkSourcePatterns
-    }
+  task jdepsReport(type: JdepsReport) {
+    target = jdepsReportDir
+  }
 
-    sourceCompatibility = "11"
-    targetCompatibility = "11"
-    
-    // Use UTF-8, don't rely on local platform encoding.
-    project.compileJava.options.encoding = "UTF-8"
-    project.compileTestJava.options.encoding = "UTF-8"
-    
-    // project.compileJava.options.compilerArgs << '-Xlint:deprecation' << '-Xlint:unchecked'
-    // project.compileTestJava.options.compilerArgs << '-Xlint:deprecation' << '-Xlint:unchecked'
-    
-    // fail on basic compiler warnings
-    project.compileJava.options.compilerArgs << "-Werror"
-    project.compileTestJava.options.compilerArgs << "-Werror"
-    
-    
-    project.sourceSets {
-      main.java.srcDirs = ['src/java']
-      main.resources.srcDirs = ['src/resources']
-      test.java.srcDirs = ['src/test']
-      test.resources.srcDirs = ['src/test-files']
-    }
-    
-    // configure tests
-    
-    if (ext.getTopLvlProject(project).equals(rootProject.project(":lucene"))) {
-      project.ext.testsPolicy = 'lucene/tools/junit4/tests.policy'
-    } else {
-      project.ext.testsPolicy = 'lucene/tools/junit4/solr-tests.policy'
+  task listDependencies(type: ListDeps) {
+    group = 'Help'
+    description = "List sorted dependencies and counts for a module."
+  }
+
+  task unusedDependencies {
+    group = 'Help'
+    description = "Lists dependencies that may be unused for a module."
+    task unusedDeps(type: UnusedDeps) {
+      inputDirectory jdepsReportDir
     }
+    unusedDeps.dependsOn jdepsReport
+    dependsOn unusedDeps
+  }
 
-    project.apply from: mfile(rootProjectDir, 'buildSrc/common/configure-test.gradle')
+  project(':buildSrc').tasks.unusedDeps.enabled = false
 
-    task sourceJar(type: Jar) {
-      classifier 'sources'
-      from sourceSets.main.allJava
-    }
-    jar.dependsOn sourceJar
-    
-    javadoc {
-      options.encoding = 'UTF-8'
-    }
-    
-    task packageJavadoc(type: Jar) {
-      classifier = 'javadoc'
-      from javadoc
-    }
-    
-    configurations {
-      sourceJarOutput
-    }
-    artifacts {
-      sourceJarOutput sourceJar
-    }
-    
-    // configure maven
-    project.getPlugins().withType(MavenPublishPlugin) {
-
-      // you can add the following above the apply maven-publish plugin to allow overriding in subprojects: project.ext.set("publishOverride", true)
-      if (!project.hasProperty('publishOverride') || !project.publishOverride) {
-        publishing {
-          publications {
-            mavenJava(MavenPublication) {
-              from components.java
-              artifact(tasks.sourceJar)
-              artifact(tasks.packageJavadoc)
-            }
-          }
-        }
-      }
+  task missingDependencies {
+    group = 'Help'
+    description = "Lists classes from this module with missing runtime dependencies (we ignore scanning some root deps (ie hadoop) and some violations (ie annotations)."
+    task missingDeps(type: MissingDeps) {
+      inputDirectory jdepsReportDir
     }
+    missingDeps.dependsOn jdepsReport
+    dependsOn missingDeps
   }
-}
 
-// *** lucene-solr root project config - configure the root project
-configure(rootProject) {
-  
-  // root project config
-  
-  // TODO: enable the modified files checking only for jenkins runs! sysprop?
-  tasks.create('checkWorkingCopy', CheckWorkingCopy, false)
-  
-  
-  task testTimes(type: TopHints) {
-    group = 'Tests'
-    description = "Show the slowest tests (averages)."
-  }
-  
-  task pristineClean(type: PristineClean) {}
-  
-  task defaultUserConfig(type: SetDefaultUserConfig) {
-    group = 'Build Setup'
-    description = "Sets recommended starting build property values in ~/.gradle/gradle.properties. Use --agressive for better build performance. WARNING! This WILL modify your gradle.properties file."
-  }
-  
-  ext.testsResults = [] // test result summaries
+  project(':buildSrc').tasks.missingDeps.enabled = false
   
-  gradle.buildFinished {
-      def allResults = ext.testsResults
-  
-      if (!allResults.isEmpty()) {
-          printResults allResults
+  // configure maven
+  project.getPlugins().withType(MavenPublishPlugin) {
+
+    // you can add the following above the apply maven-publish plugin to allow overriding in subprojects: project.ext.set("publishOverride", true)
+    if (!project.hasProperty('publishOverride') || !project.publishOverride) {
+      publishing {
+        publications {
+          mavenJava(MavenPublication) {
+            from components.java
+            artifact(tasks.sourceJar)
+            artifact(tasks.packageJavadoc)
+          }
+        }
       }
+    }
   }
-}
 
-// *** all projects config
-configure(allprojects) {
-  
-  // -> lucene-solr IDE config - setup eclipse and idea
-  
-  apply plugin: 'eclipse'
-  apply plugin: 'idea'
-  
-  plugins.withType(JavaPlugin) {
-    project.apply from: mfile(rootProjectDir, 'buildSrc/ide/eclipse.gradle')
-    project.apply from: mfile(rootProjectDir, 'buildSrc/ide/idea.gradle')
-  }
-  
   // dependencies block that applies to all projects
   dependencies {
     configurations.all {
@@ -262,74 +236,127 @@ configure(allprojects) {
       exclude group: 'javax.xml.stream', module: 'stax-api'
       exclude group: 'stax', module: 'stax-api'
       exclude group: 'stax', module: 'stax'
-      
+
       // logging jars we don't want, we use slf4j
       exclude group: 'log4j', module: 'log4j'
       exclude group: 'commons-logging', module: 'commons-logging'
-      
+
       // exclude annotation jars that come with guava
       exclude group: 'com.google.code.findbugs', module: 'jsr305'
       exclude group: 'org.checkerframework', module: 'checker-qual'
       exclude group: 'com.google.errorprone', module: 'error_prone_annotations'
       exclude group: 'com.google.j2objc', module: 'j2objc-annotations'
       exclude group: 'org.codehaus.mojo', module: 'animal-sniffer-annotations'
-      
+
       exclude group: 'org.slf4j', module: 'slf4j-log4j12' // zk and perhaps others can bring in log4j12 binding
-      
+
       exclude group: 'xml-apis', module: 'xml-apis' // somehow can be inconsistenly brought in by xerces:xercesImpl - exlude it
     }
-    
+
     modules {
       module("commons-logging:commons-logging") { replacedBy("org.slf4j:jcl-over-slf4j") }
       module("log4j:log4j") { replacedBy("org.slf4j:log4j-over-slf4j") }
     }
   }
-  
-  File jdepsReportDir = mfile(project.buildDir, 'jdepsreport')
-  
+
+
+
   plugins.withType(JavaPlugin) {
     
-    task jdepsReport(type: JdepsReport) {
-      target = jdepsReportDir
+    sourceCompatibility = "11"
+    targetCompatibility = "11"
+
+    // Use UTF-8, don't rely on local platform encoding.
+    compileJava.options.encoding = "UTF-8"
+    compileTestJava.options.encoding = "UTF-8"
+
+    // project.compileJava.options.compilerArgs << '-Xlint:deprecation' << '-Xlint:unchecked'
+    // project.compileTestJava.options.compilerArgs << '-Xlint:deprecation' << '-Xlint:unchecked'
+
+    // fail on basic compiler warnings
+    compileJava.options.compilerArgs << "-Werror"
+    compileTestJava.options.compilerArgs << "-Werror"
+
+
+    sourceSets {
+      main.java.srcDirs = ['src/java']
+      main.resources.srcDirs = ['src/resources']
+      test.java.srcDirs = ['src/test']
+      test.resources.srcDirs = ['src/test-files']
     }
+
+    project.apply from: mfile(rootDir, 'buildSrc/common/configure-test.gradle')
     
-    task listDependencies(type: ListDeps) {
-      group = 'Help'
-      description = "List sorted dependencies and counts for a module."
+    task sourceJar(type: Jar) {
+      classifier 'sources'
+      from sourceSets.main.allJava
     }
-    
-    task unusedDependencies {
-      group = 'Help'
-      description = "Lists dependencies that may be unused for a module."
-      task unusedDeps(type: UnusedDeps) {
-        inputDirectory jdepsReportDir
-      }
-      unusedDeps.dependsOn jdepsReport
-      dependsOn unusedDeps
+    jar.dependsOn sourceJar
+
+    javadoc {
+      options.encoding = 'UTF-8'
     }
-    
-    project(':buildSrc').tasks.unusedDeps.enabled = false
-    
-    task missingDependencies {
-      group = 'Help'
-      description = "Lists classes from this module with missing runtime dependencies (we ignore scanning some root deps (ie hadoop) and some violations (ie annotations)."
-      task missingDeps(type: MissingDeps) {
-        inputDirectory jdepsReportDir
-      }
-      missingDeps.dependsOn jdepsReport
-      dependsOn missingDeps
+
+    task packageJavadoc(type: Jar) {
+      classifier = 'javadoc'
+      from javadoc
+    }
+
+    configurations {
+      sourceJarOutput
+    }
+    artifacts {
+      sourceJarOutput sourceJar
     }
-    
-    project(':buildSrc').tasks.missingDeps.enabled = false
   }
+
+
 }
 
-// *** other config
 
+// TODO: prob wont go here
+//  task checkMissingJavaDocs {
+//    group = 'Verification'
+//    description = "Checks for missing JavaDocs."
+//
+//    doLast {
+//      project.exec {
+//        workingDir project.projectDir.getAbsolutePath()
+//        executable "${python_exe}"
+//        args = [
+//          '-B',
+//          rootProjectDir.getAbsolutePath() + '/dev-tools/scripts/checkJavaDocs.py',
+//          project.projectDir.getAbsolutePath(),
+//          'class'
+//        ]
+//      }
+//    }
+//  }
+
+// TODO: check.dependsOn checkMissingJavaDocs
+
+
+
+
+// ### -> Other config
+
+
+// TODO: prob does not go here
 
 // Single JavaDocs for all modules
 
-def noJavaDocModules = ["buildSrc", "dev-tools","lucene", "solr", "solr-ref-guide", "lucene-analysis", "lucene-backward-codecs", "solr-contrib", "solr-example", "solr-example-DIH"]
+def noJavaDocModules = [
+  "buildSrc",
+  "dev-tools",
+  "lucene",
+  "solr",
+  "solr-ref-guide",
+  "lucene-analysis",
+  "lucene-backward-codecs",
+  "solr-contrib",
+  "solr-example",
+  "solr-example-DIH"
+]
 def javaDocProjects = subprojects.findAll { project -> !noJavaDocModules.contains(project.name)}
 
 // project.afterEvaluate{
diff --git a/buildSrc/build-wdocker-test/setup-script-for-test.sh b/buildSrc/build-wdocker-test/setup-script-for-test.sh
index 16c4785..4097cc1 100644
--- a/buildSrc/build-wdocker-test/setup-script-for-test.sh
+++ b/buildSrc/build-wdocker-test/setup-script-for-test.sh
@@ -31,7 +31,7 @@ function errexit() {
   set +x
 
   if [ ! "${EXP_EXIT}" = "q" ]; then
-    echo "${ERR_LN} Error in ${BASH_SOURCE[1]}:${BASH_LINENO[0]}. '${last_cmd}' exited with code ${err}"
+    echo -w "\n\n\n${ERR_LN} Error in ${BASH_SOURCE[1]}:${BASH_LINENO[0]}. '${last_cmd}' exited with code ${err}"
   fi
   # print stack trace
   if [ ${#FUNCNAME[@]} -gt 2 ]; then
@@ -47,7 +47,7 @@ function errexit() {
   elif [ "${EXP_EXIT}" = "q" ]; then
     exit 0;
   else
-    echo "${ERR_LN} Exiting with code ${code}"
+    echo -e"${ERR_LN} Exiting with code ${code}\n\n\n"
     exit "${code}"
   fi
   
diff --git a/buildSrc/build-wdocker-test/start.sh b/buildSrc/build-wdocker-test/start.sh
index 7735d09..e27f67f 100644
--- a/buildSrc/build-wdocker-test/start.sh
+++ b/buildSrc/build-wdocker-test/start.sh
@@ -60,8 +60,8 @@ fi
 
 echo "Starting the container ..."
 
-# we don't currently use :cached or :delegated for osx perf, or copy or map in .gradle for caching becuase of issues getting things to work on linux and osx - ideally we use linux because osx will likely be very slow
+# we don't currently use :cached or :delegated for osx perf becuase of issues getting things to work on linux and osx - ideally we use linux because osx will likely be very slow
 # this will also likley download a lot on first run
 
-docker run -itd --user ${UID} --name=${CONTAINER_NAME} -v "${script_dir}/../..":/home/lucene/project -h ${CONTAINER_NAME} ${CONTAINER_NAME} || { exit 1; }
+docker run -itd --user ${UID} --name=${CONTAINER_NAME} -v "${script_dir}/../..":/home/lucene/project -v ~/.gradle/caches/modules-2/files-2.1:/root/.gradle/caches/modules-2/files-2.1 -v ~/.gradle/wrapper:/root/.gradle/wrapper -h ${CONTAINER_NAME} ${CONTAINER_NAME} || { exit 1; }
 
diff --git a/buildSrc/build-wdocker-test/test-rat-sources.sh b/buildSrc/build-wdocker-test/test-rat-sources.sh
index 3d084ec..54b7a93 100644
--- a/buildSrc/build-wdocker-test/test-rat-sources.sh
+++ b/buildSrc/build-wdocker-test/test-rat-sources.sh
@@ -21,9 +21,15 @@ command -v docker >/dev/null 2>&1 || { echo "docker must be installed to run thi
 
 OPTIND=1  # Reset in case getopts has been used previously in the shell.
 
-while getopts ":" opt; do
+results="undefined"
+
+
+while getopts ":r:" opt; do
     case "$opt" in
-    *)  
+    r)
+      results="${OPTARG}"
+      ;;
+    *)
       echo -e "\n-----> Invalid arg: $OPTARG  If it is a valid option, does it take an argument?"
       usage
       exit 1
@@ -43,16 +49,26 @@ exec() {
   docker exec --user ${UID} $2 -t ${CONTAINER_NAME} bash -c "$1"
 }
 
+writeResult() {
+  echo "$1" > ${results}
+}
+
 set -x
 
 exec_args=""
-gradle_args="--console=plain -x verifyLocks"
+gradle_args="--console=plain"
 
 # NOTE: we don't clean right now, as it would wipe out buildSrc/build on us for the host, but buildTest dependsOn clean
 
+
+echo "\n\nTestChecks#testRatSources"
+
+
+echo "${HOME}"
+
 # first check that rat passes
 cmd="cd /home/lucene/project;./gradlew ${gradle_args} ratSources"
-exec "${cmd}" "${exec_args}" || { exit 1; }
+exec "${cmd}" "${exec_args}" || { writeResult "The ratSources task did not pass when it should have"; exit 1; }
 
 # create an xml file with no license in lucene
 cmd="touch /home/lucene/project/lucene/core/src/java/org/no_license_test_file.xml"
@@ -61,11 +77,12 @@ exec "${cmd}" "${exec_args}" || { exit 1; }
 # test that rat fails on our test file
 cmd="cd /home/lucene/project;./gradlew ${gradle_args} ratSources"
 if exec "${cmd}" "${exec_args}"; then
-  echo "rat should fail!"
+  echo "The ratSources task passed when it should not have!"
+  writeResult "The ratSources task passed when it should not have!";
   exit 1 # rat should fail!
 fi
 
-# clean test file
+# clean test file - also done by the java test parent in case of failure
 cmd="rm /home/lucene/project/lucene/core/src/java/org/no_license_test_file.xml"
 exec "${cmd}" "${exec_args}" || { exit 1; }
 
diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle
index 2e2902f..9bbc1e7 100644
--- a/buildSrc/build.gradle
+++ b/buildSrc/build.gradle
@@ -19,7 +19,7 @@ apply plugin: 'groovy'
 apply plugin: 'java'
 apply plugin: 'java-gradle-plugin'
 
-buildDir = file('build')
+buildDir = file("../build/${project.name}")
 
 group = 'org.apache.lucene.gradle'
 
@@ -119,9 +119,3 @@ clean.doLast {
   // hack for eclipse issue
   file("$buildDir/pluginUnderTestMetadata").mkdirs()
 }
-
-if (project.rootProject != project) {
-  forbiddenApis {
-    signatures -= ['java.io.File']
-  }
-}
diff --git a/buildSrc/common/build-help.gradle b/buildSrc/common/build-help.gradle
index ed1a3e1..fb85c81 100644
--- a/buildSrc/common/build-help.gradle
+++ b/buildSrc/common/build-help.gradle
@@ -20,7 +20,7 @@ task buildTestsHelp {
   description = "How to run Lucene and Solr tests and the options that are available to you."
 
   doLast {
-    println file("${project(':buildSrc').projectDir}/common/help-text/testHelp.txt").text
+    println file("${rootDir}/buildSrc/common/help-text/testHelp.txt").text
   }
 }
 
@@ -28,7 +28,7 @@ task buildDependenciesHelp {
   group = 'Help (Build Documentation)'
   description = "How dependencies are managed and what you need to know to change them."
   doLast {
-    println file("${project(':buildSrc').projectDir}/common/help-text/buildDependenciesHelp").text
+    println file("${rootDir}/buildSrc/common/help-text/buildDependenciesHelp.txt").text
   }
 }
 
diff --git a/buildSrc/common/configure-ext.gradle b/buildSrc/common/configure-ext.gradle
index 0a3a2a9..cdf081a 100644
--- a/buildSrc/common/configure-ext.gradle
+++ b/buildSrc/common/configure-ext.gradle
@@ -17,6 +17,7 @@
 
 import org.gradle.internal.logging.text.StyledTextOutput;
 import org.gradle.internal.logging.text.StyledTextOutputFactory;
+import org.gradle.api.Project;
 import static org.gradle.internal.logging.text.StyledTextOutput.Style;
 
 def initialRandomSeed = {
@@ -36,33 +37,39 @@ allprojects {
   ext.filePath = { path -> file(path).getAbsolutePath() }
   // sugar multi part File
   ext.mfile = { file1, file2 -> new File(file(file1), file2.toString()) }
-  
-  ext.getTopLvlProject = { proj ->
-    def topLvlProject
-    if (proj.group ==~ /.*?\.lucene(?:\.\w+)?/) {
-      topLvlProject = project.project(":lucene")
-    } else if (proj.group ==~ /.*?\.solr(?:\.\w+)?/) {
-      topLvlProject = project.project(":solr")
+
+  ext.getTopLvlProject = { Project proj ->
+    Project projectIt
+    if (proj == null) {
+      projectIt = project
+    } else {
+      projectIt = proj
+    }
+    if (projectIt.getParent() == null) {
+      return projectI
+    }
+    while(projectIt.getParent() != projectIt.rootProject) {
+      projectIt = projectIt.getParent()
     }
-    return topLvlProject
+    return projectIt
   }
 
   // keep the random seed constant for each subproject.
   ext.randomSeed = initialRandomSeed
 
   ext.printResults = {results ->
-    
+
     def allResults = new ArrayList()
     results.collect { allResults.add(it.getProjectAndTask() + ' ' + it.getSummary()) }
-    
-    // max line length 
+
+    // max line length
     def maxLength = allResults*.readLines().flatten().collect { it.length() }.max()
-    
+
     def out = services.get(StyledTextOutputFactory).create("out")
     def borderStyle
     def headerStyle
     def topBorderStyle
-    
+
     for (def i = 0; i < results.size(); i++) {
       def result = results.get(i)
       if (result.getSuccess()) {
@@ -74,27 +81,25 @@ allprojects {
         headerStyle = Style.FailureHeader
         topBorderStyle = Style.Failure
       }
-      
+
       out.style(topBorderStyle).println("┌${"${"─" * maxLength}"}┐")
 
       result.collect {
-        String projectAndTask = it.getProjectAndTask()
-        String summary = it.getSummary()
-        boolean success = it.getSuccess()
-        int line = 0
-        summary.readLines().collect {
-          line++
-          if (line == 1) {
-            out.style(borderStyle).text('│').style(headerStyle).text(projectAndTask).style(Style.Normal).text(' ' + it + ' ' * (maxLength - (projectAndTask.length() + 1 + it.length()))).style(borderStyle).println('│')
-          } else {
-            out.style(borderStyle).text('│').style(Style.Normal).text(it + ' ' * (maxLength - it.length())).style(borderStyle).println('│')
-          }
-        }.join("\n")
-      }.join("\n├${"${"─" * maxLength}"}┤\n") // Add separator between entries
-      println "└${"${"─" * maxLength}"}┘" // bottom border
-    }
-
-  
-  }
-  
+      String projectAndTask = it.getProjectAndTask()
+      String summary = it.getSummary()
+      boolean success = it.getSuccess()
+      int line = 0
+      summary.readLines().collect {
+        line++
+        if (line == 1) {
+          out.style(borderStyle).text('│').style(headerStyle).text(projectAndTask).style(Style.Normal).text(' ' + it + ' ' * (maxLength - (projectAndTask.length() + 1 + it.length()))).style(borderStyle).println('│')
+        } else {
+          out.style(borderStyle).text('│').style(Style.Normal).text(it + ' ' * (maxLength - it.length())).style(borderStyle).println('│')
+        }
+      }.join("\n")
+    }.join("\n├${"${"─" * maxLength}"}┤\n") // Add separator between entries
+    println "└${"${"─" * maxLength}"}┘" // bottom border
+   }
+ }
+ 
 }
\ No newline at end of file
diff --git a/buildSrc/common/configure-test.gradle b/buildSrc/common/configure-test.gradle
index 9523112..75a4f6b 100644
--- a/buildSrc/common/configure-test.gradle
+++ b/buildSrc/common/configure-test.gradle
@@ -15,10 +15,11 @@
  * limitations under the License.
  */
 
- import org.gradle.api.tasks.testing.logging.TestExceptionFormat
- import org.gradle.api.tasks.testing.logging.TestLogEvent
- import groovy.time.TimeCategory
- import org.apache.lucene.gradle.TestResultObj
+import org.gradle.api.tasks.testing.logging.TestExceptionFormat
+import org.gradle.api.tasks.testing.logging.TestLogEvent
+import groovy.time.TimeCategory
+import org.apache.lucene.gradle.TestResultObj
+import org.apache.tools.ant.Project
 
 test {
   group = 'Tests'
@@ -74,32 +75,26 @@ test {
     }
   }
 
-  minHeapSize = "128m"
+  minHeapSize = "256m"
   maxHeapSize = "512m"
 
   jvmArgs +=  "-XX:+UseG1GC"
-  jvmArgs +=  "-XX:MaxGCPauseMillis=500" 
+  jvmArgs +=  "-XX:MaxGCPauseMillis=500"
   jvmArgs +=  "-XX:+UnlockExperimentalVMOptions"
   jvmArgs +=  "-XX:G1MaxNewSizePercent=30"
   jvmArgs +=  "-XX:G1NewSizePercent=5"
   jvmArgs +=  "-XX:G1HeapRegionSize=32M"
   jvmArgs +=  "-XX:InitiatingHeapOccupancyPercent=70"
 
-  // TODO: move this to a property in subprojects{} configuration under each respective lucene/ solr/ build.
-  // OR REMOVE IT ENTIRELY (we don't seem to need it anywhere in tests!)
-  def commonDir
-  if (project.ext.getTopLvlProject(project).equals(rootProject.project(":lucene"))) {
-    commonDir = rootProject.project(":lucene").projectDir
-  } else {
-    commonDir = rootProject.project(":solr").projectDir
-  }
+  // this allows tests to read classes and resources form other projects with the security manager
+  def commonDir = "${rootDir}/build"
+
   systemProperty 'common.dir', "${commonDir}"
 
-  def workingDir = file("${projectDir}/build/tests")
+  workingDir = file("${projectDir}/build")
   def tmpDir = file("${workingDir}/build/tests")
 
   doFirst {
-    workingDir.mkdirs()
     tmpDir.mkdirs()
   }
 
@@ -107,6 +102,7 @@ test {
   // to point at user.dir.
   systemProperty 'tests.src.home', System.getenv('user.dir')
 
+  systemProperty 'common.dir', "${commonDir}"
   systemProperty 'build.dir', project.buildDir
   systemProperty 'tempDir', tmpDir
   systemProperty 'java.io.tmpdir', tmpDir
@@ -114,7 +110,6 @@ test {
   systemProperty 'jetty.testMode', '1'
   systemProperty 'jetty.insecurerandom', '1'
   systemProperty 'jdk.map.althashing.threshold', '0'
-  systemProperty 'solr.directoryFactory', 'org.apache.solr.core.MockDirectoryFactory'
 
   systemProperty 'tests.seed', randomSeed
 
@@ -148,21 +143,25 @@ test {
   // Enable assertions depending on tests.asserts.
   enableAssertions Boolean.parseBoolean(systemProperties['tests.asserts'])
 
-  // replaces default random source to the nonblocking variant 
+  // replaces default random source to the nonblocking variant
   systemProperty 'java.security.egd', 'file:/dev/./urandom'
-  systemProperty 'java.security.manager', 'org.apache.lucene.util.TestSecurityManager'
-  systemProperty 'java.security.policy', file("${rootDir}/${testsPolicy}")
+  
+  if (project.hasProperty('testsPolicy')) {
+    systemProperty 'java.security.manager', 'org.apache.lucene.util.TestSecurityManager'
+    systemProperty 'java.security.policy', "${testsPolicy}"
+  }
 
-  if (project.ext.properties.containsKey('tests_jvms')) {
-    def testsJvms = project.ext.properties.tests_jvms
+  if (project.hasProperty('tests_jvms')) {
+    def testsJvms = tests_jvms
     maxParallelForks = Integer.parseInt(testsJvms)
   } else {
     maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1
   }
 
-  def testsFailFast = project.ext.properties.tests_failfast
-  if (testsFailFast) {
-    failFast = true
+  if (project.hasProperty('tests_failfast')) {
+    if (Boolean.parseBoolean(tests_failfast)) {
+      failFast = true
+    }
   }
 }
 
diff --git a/buildSrc/ide/eclipse.gradle b/buildSrc/ide/eclipse.gradle
index b309743..f46464f 100644
--- a/buildSrc/ide/eclipse.gradle
+++ b/buildSrc/ide/eclipse.gradle
@@ -15,43 +15,87 @@
  * limitations under the License.
  */
 
+task cleanSettingsDir {
+  doLast { delete(file('.settings')) }
+}
+cleanEclipse.dependsOn cleanSettingsDir
+
+if (project.name == 'buildSrc') {
+  project.tasks.eclipse.dependsOn { project.tasks.pluginUnderTestMetadata }
+}
+
+task createSettingsDir {
+  doLast {
+    file('.settings').mkdirs()
+    def uiPrefFile = mfile(project.rootProject.projectDir, "buildSrc/ide/resources/org.eclipse.jdt.ui.prefs")
+    def resourcePrefFile = mfile(project.rootProject.projectDir, "buildSrc/ide/resources/org.eclipse.core.resources.prefs")
+    def corePrefFile = mfile(project.rootProject.projectDir, "buildSrc/ide/resources/org.eclipse.jdt.core.prefs")
+    copy {
+      from {
+        [
+          uiPrefFile,
+          resourcePrefFile,
+          corePrefFile
+        ]
+      }
+      into file('.settings')
+    }
+
+    // Jetty mod files make eclipse sad
+    file('.settings/org.eclipse.wst.validation.prefs').text = """
+eclipse.preferences.version=1
+override=true
+suspend=true
+vf.version=3
+"""
+  }
+}
+
+project.tasks.eclipse.dependsOn createSettingsDir
+
 eclipse {
   project {
-    if (project.name.equals('lucene-benchmark')) {
-      resourceFilter {
-        appliesTo = 'FOLDERS'
-        type = 'EXCLUDE_ALL'
-        matcher {
-          id = 'org.eclipse.ui.ide.multiFilter'
-          arguments = '1.0-projectRelativePath-matches-true-true-work|temp'
-        }
+    // ignore common folders we don't want the ide busy looking at
+    resourceFilter {
+      appliesTo = 'FOLDERS'
+      type = 'EXCLUDE_ALL'
+      matcher {
+        id = 'org.eclipse.ui.ide.multiFilter'
+        arguments = '1.0-projectRelativePath-matches-true-true-work|temp|build'
       }
     }
+    linkedResource name: 'build-eclipse', type: '2', location: mfile(rootProject.projectDir, "build-eclipse/${project.name}").getAbsolutePath()
   }
-  
+
   classpath {
 
-    defaultOutputDir = file('eclipse-build/default')
-    
+
+    String outputDir = 'build-eclipse'
+
+    defaultOutputDir = mfile(outputDir, "${project.name}")
+
     downloadSources = true
     downloadJavadoc = true
-    
+
     file.beforeMerged { classpath ->
+
       // some projects might have a tools src set, so add the tools configuration if it exists
       def extraConfs = ['tools', 'refGuide']
-      configurations.all.findAll { c -> extraConfs.contains(c.name) }.each { plusConfigurations += [ it ]}
+      configurations.all.findAll { c -> extraConfs.contains(c.name) }.each { plusConfigurations += [it]}
+
     }
 
     file.whenMerged { classpath ->
       Set<String> entries = new HashSet<>()
 
-      
-      classpath.entries.each { entry ->
 
+      classpath.entries.each { entry ->
         if ( entry.kind == 'src' && entry.hasProperty('output')) {
-          // use default Output for all source-folders
-          // entry.output = null
-          entry.output = entry.output.replaceAll('bin/', 'eclipse-build/')
+          def out = entry.output
+
+          if (out != null) {
+            entry.output = out.replaceAll('bin/', 'build-eclipse' + '/')
+          }
         }
         if ( entry.kind == 'src' && entry.hasProperty('path')) {
 
@@ -61,14 +105,14 @@ eclipse {
           }
         }
       }
-      
+
       // add JRE_CONTAINER
       classpath.entries.removeAll { entry -> entry.kind == 'con' && entry.path.startsWith('org.eclipse.jdt.launching.JRE_CONTAINER') }
       def jreContainer = new org.gradle.plugins.ide.eclipse.model.Container('org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11')
       jreContainer.getEntryAttributes().put("module", "true")
-      
+
       classpath.entries.add(jreContainer)
-      
+
       classpath.entries.each { entry ->
         if ( entry.kind == 'lib') {
           entry.exported = true
@@ -77,36 +121,16 @@ eclipse {
           entry.exported = false
         }
       }
-      
+
       // hack to get src for gradle
       String gradleHome = gradle.getGradleHomeDir().absolutePath.replace(File.separator, '/')
       String gradleSrc = "${gradleHome}/src"
       classpath.entries.each { entry ->
-          if ((entry in org.gradle.plugins.ide.eclipse.model.AbstractLibrary) && (entry.library.path.contains('generated-gradle-jars'))) {
-            entry.sourcePath = new org.gradle.plugins.ide.eclipse.model.internal.FileReferenceFactory().fromPath(gradleSrc)
-          }
-      }
-
-      def uiPrefFile = mfile(project(":buildSrc").projectDir, "ide/resources/org.eclipse.jdt.ui.prefs")
-      def resourcePrefFile = mfile(project(":buildSrc").projectDir, "ide/resources/org.eclipse.core.resources.prefs")
-      def corePrefFile = mfile(project(":buildSrc").projectDir, "ide/resources/org.eclipse.jdt.core.prefs")
-      copy {
-         from { [uiPrefFile, resourcePrefFile, corePrefFile] }
-         into file('.settings')
-       }
-
-      if (project.name == 'buildSrc') {
-        project.tasks.pluginUnderTestMetadata
+        if ((entry in org.gradle.plugins.ide.eclipse.model.AbstractLibrary) && (entry.library.path.contains('generated-gradle-jars'))) {
+          entry.sourcePath = new org.gradle.plugins.ide.eclipse.model.internal.FileReferenceFactory().fromPath(gradleSrc)
+        }
       }
 
-      // Jetty mod files make eclipse sad
-      file('.settings').mkdirs()
-      file('.settings/org.eclipse.wst.validation.prefs').text = """
-eclipse.preferences.version=1
-override=true
-suspend=true
-vf.version=3
-"""
     }
   }
 }
diff --git a/buildSrc/src/buildTest/java/TestChecks.java b/buildSrc/src/buildTest/java/TestChecks.java
index dbaeb41..9b425ff 100644
--- a/buildSrc/src/buildTest/java/TestChecks.java
+++ b/buildSrc/src/buildTest/java/TestChecks.java
@@ -14,18 +14,33 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+import java.nio.file.Files;
+import java.nio.file.LinkOption;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
 public class TestChecks extends BaseTestClass {
   
+
+  
+  private Path tempDirWithPrefix;
+  
+  private String resultFile = "/tmp/buildTestResult.txt";
+  
   public TestChecks() {
 
   }
   
   @Before
   public void setUp() throws Exception {
+    tempDirWithPrefix = Files.createTempDirectory("LuceneSolrBuildTest");
+    resultFile = Paths.get(tempDirWithPrefix.toString(), "testResult.txt").toString();
+    
     cleanTestFiles();
   }
   
@@ -35,30 +50,49 @@ public class TestChecks extends BaseTestClass {
   }
 
   private void cleanTestFiles() throws Exception {
-    String[] cmd = new String[]{"bash", "-c", "docker exec --user ${UID} -t ${CONTAINER_NAME} bash -c \"rm /home/lucene/project/solr/core/src/test/org/no_license_test_file.java\""};
+    String[] cmd = new String[]{"bash", "-c", "docker exec --user ${UID} -t ${CONTAINER_NAME} bash -c \"rm /home/lucene/project/solr/core/src/test/org/no_license_test_file.java 2>/dev/null \""};
     runCmd(cmd, env, false, false);
     
-    cmd = new String[]{"bash", "-c", "docker exec --user ${UID} -t ${CONTAINER_NAME} bash -c \"rm /home/lucene/project/lucene/core/src/java/org/no_license_test_file.xml\""};
+    cmd = new String[]{"bash", "-c", "docker exec --user ${UID} -t ${CONTAINER_NAME} bash -c \"rm /home/lucene/project/lucene/core/src/java/org/no_license_test_file.xml 2>/dev/null \""};
     runCmd(cmd, env, false, false);
     
     
-    cmd = new String[]{"bash", "-c", "docker exec --user ${UID} -t ${CONTAINER_NAME} bash -c \"rm /home/lucene/project/solr/contrib/clustering/src/java/org/tab_file.xml\""};
+    cmd = new String[]{"bash", "-c", "docker exec --user ${UID} -t ${CONTAINER_NAME} bash -c \"rm /home/lucene/project/solr/contrib/clustering/src/java/org/tab_file.xml 2>/dev/null \""};
     runCmd(cmd, env, false, false);
+    try {
+      Files.delete(tempDirWithPrefix);
+    } catch (NoSuchFileException e) {
+      // fine
+    }
   }
   
   @Test
   public void testRatSources() throws Exception {
     System.out.println("Start test-rat-sources.sh test in Docker container (" + env + ") ...");
-    String[] cmd = new String[]{"bash", "build-wdocker-test/test-rat-sources.sh"};
+    String[] cmd = new String[]{"bash", "build-wdocker-test/test-rat-sources.sh", "-r", resultFile  };
     PbResult result = runCmd(cmd, env, false, false, false);
-    assertEquals("Testing test-rat-sources.sh failed", 0, result.returnCode);
+    
+    String msg = "";
+    
+    if (Files.exists(Paths.get(resultFile), LinkOption.NOFOLLOW_LINKS)) {
+      msg =  Files.readString(Paths.get(resultFile));
+    }
+    
+    assertEquals("Testing test-rat-sources.sh failed: " + msg, 0, result.returnCode);
   }
 
   @Test
   public void testCheckSources() throws Exception {
     System.out.println("Start test-check-sources.sh test in Docker container (" + env + ") ...");
-    String[] cmd = new String[]{"bash", "build-wdocker-test/test-check-sources.sh"};
+    String[] cmd = new String[]{"bash", "build-wdocker-test/test-check-sources.sh", "-r", resultFile  };
     PbResult result = runCmd(cmd, env, false, false, false);
-    assertEquals("Testing test-check-sources.sh failed", 0, result.returnCode);
+    
+    String msg = "";
+    
+    if (Files.exists(Paths.get(resultFile), LinkOption.NOFOLLOW_LINKS)) {
+      msg =  Files.readString(Paths.get(resultFile));
+    }
+    
+    assertEquals("Testing test-check-sources.sh failed: " + msg, 0, result.returnCode);
   }
 }
diff --git a/buildSrc/src/main/groovy/org/apache/lucene/gradle/TopHints.groovy b/buildSrc/src/main/groovy/org/apache/lucene/gradle/TopHints.groovy
index 776b8f3..7b81e9a 100644
--- a/buildSrc/src/main/groovy/org/apache/lucene/gradle/TopHints.groovy
+++ b/buildSrc/src/main/groovy/org/apache/lucene/gradle/TopHints.groovy
@@ -28,7 +28,7 @@ class TopHints extends DefaultTask {
   
   
   public TopHints() {
-    dependsOn project.rootProject.project(':buildSrc').tasks.setupAntPaths
+    dependsOn { project(':buildSrc').tasks.setupAntPaths }
   }
   
   @TaskAction
diff --git a/buildSrc/src/main/groovy/org/apache/lucene/gradle/checks/RatSources.groovy b/buildSrc/src/main/groovy/org/apache/lucene/gradle/checks/RatSources.groovy
index 94e4be3..472b32d 100644
--- a/buildSrc/src/main/groovy/org/apache/lucene/gradle/checks/RatSources.groovy
+++ b/buildSrc/src/main/groovy/org/apache/lucene/gradle/checks/RatSources.groovy
@@ -38,7 +38,7 @@ class RatSources extends DefaultTask {
   List<String> excludes = new ArrayList<>()
   
   public RatSources() {
-    dependsOn project.rootProject.project(':buildSrc').tasks.setupAntPaths
+    dependsOn { project.rootProject.project(':buildSrc').tasks.setupAntPaths }
   }
   
   @Optional
@@ -152,4 +152,3 @@ class RatSources extends DefaultTask {
   }
 }
 
-
diff --git a/buildSrc/src/main/groovy/org/apache/lucene/gradle/deps/MissingDeps.groovy b/buildSrc/src/main/groovy/org/apache/lucene/gradle/deps/MissingDeps.groovy
index 8673402..b4d59a1 100644
--- a/buildSrc/src/main/groovy/org/apache/lucene/gradle/deps/MissingDeps.groovy
+++ b/buildSrc/src/main/groovy/org/apache/lucene/gradle/deps/MissingDeps.groovy
@@ -79,7 +79,7 @@ class MissingDeps extends DefaultTask {
     // make sure ant task logging shows up by default
     ant.lifecycleLogLevel = "INFO"
     
-    def topLvlProject = getTopLvlProject(project)
+    def topLvlProject = project.getTopLvlProject()
     
     File dotFile = project.mfile(inputDirectory, 'jdepsDir/' + topLvlProject.name +  "/" + "${project.name}-${project.version}/${project.name}-${project.version}.jar.dot")
     
@@ -248,18 +248,6 @@ class MissingDeps extends DefaultTask {
     return this
   }
   
-  protected Project getTopLvlProject(Project proj) {
-    def topLvlProject
-    if (proj.group ==~ /.*?\.lucene(?:\.\w+)?/) {
-      topLvlProject = project.project(":lucene")
-    } else if (proj.group ==~ /.*?\.solr(?:\.\w+)?/) {
-      topLvlProject = project.project(":solr")
-    } else {
-      throw new GradleException("Could not determine top level project for " + proj)
-    }
-    return topLvlProject
-  }
-  
   public void addExclusionsFrom(Project fromProject) {
     project.evaluationDependsOn(fromProject.path)
     
diff --git a/buildSrc/src/main/java/org/apache/lucene/gradle/LicenseCheckTask.java b/buildSrc/src/main/java/org/apache/lucene/gradle/LicenseCheckTask.java
index b9b4781..6939855 100644
--- a/buildSrc/src/main/java/org/apache/lucene/gradle/LicenseCheckTask.java
+++ b/buildSrc/src/main/java/org/apache/lucene/gradle/LicenseCheckTask.java
@@ -1,3 +1,19 @@
+/*
+ * 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.gradle;
 
 import org.gradle.api.DefaultTask;
diff --git a/lucene/analysis/icu/build.gradle b/lucene/analysis/icu/build.gradle
index 4ec5fa3..c3ecf43 100644
--- a/lucene/analysis/icu/build.gradle
+++ b/lucene/analysis/icu/build.gradle
@@ -28,7 +28,7 @@ configurations {
 dependencies {
   
   api project(':lucene:lucene-core')
-  api project(':lucene:analysis:lucene-analyzers-common')
+  api project(':lucene:lucene-analyzers:lucene-analyzers-common')
   
   api ('com.ibm.icu:icu4j')
   
diff --git a/lucene/analysis/kuromoji/build.gradle b/lucene/analysis/kuromoji/build.gradle
index b3a2f6d..6c40390 100644
--- a/lucene/analysis/kuromoji/build.gradle
+++ b/lucene/analysis/kuromoji/build.gradle
@@ -28,7 +28,7 @@ configurations {
 dependencies {
   
   implementation project(':lucene:lucene-core')
-  implementation project(':lucene:analysis:lucene-analyzers-common')
+  implementation project(':lucene:lucene-analyzers:lucene-analyzers-common')
   
   tools ('com.ibm.icu:icu4j')
   
diff --git a/lucene/analysis/morfologik/build.gradle b/lucene/analysis/morfologik/build.gradle
index 753c496..53008c0 100644
--- a/lucene/analysis/morfologik/build.gradle
+++ b/lucene/analysis/morfologik/build.gradle
@@ -24,7 +24,7 @@ archivesBaseName = 'lucene-analyzers-morfologik'
 dependencies {
 
   implementation project(':lucene:lucene-core')
-  implementation project(':lucene:analysis:lucene-analyzers-common')
+  implementation project(':lucene:lucene-analyzers:lucene-analyzers-common')
   
   implementation ('org.carrot2:morfologik-polish')
   implementation ('org.carrot2:morfologik-fsa')
diff --git a/lucene/analysis/nori/build.gradle b/lucene/analysis/nori/build.gradle
index d253c5f..38a2311 100644
--- a/lucene/analysis/nori/build.gradle
+++ b/lucene/analysis/nori/build.gradle
@@ -19,15 +19,13 @@ apply plugin: 'java-library'
 apply plugin: 'maven-publish'
 apply plugin: org.apache.lucene.gradle.dist.PartOfDist
 
-archivesBaseName = 'lucene-analyzers-nori'
-
 configurations {
   tools
 }
 
 dependencies {
   implementation project(':lucene:lucene-core')
-  implementation project(':lucene:analysis:lucene-analyzers-common')
+  implementation project(':lucene:lucene-analyzers:lucene-analyzers-common')
   
   tools ('com.ibm.icu:icu4j')
   
diff --git a/lucene/analysis/opennlp/build.gradle b/lucene/analysis/opennlp/build.gradle
index a43cb38..f332a22 100644
--- a/lucene/analysis/opennlp/build.gradle
+++ b/lucene/analysis/opennlp/build.gradle
@@ -23,7 +23,7 @@ archivesBaseName = 'lucene-analyzers-opennlp'
 
 dependencies {
   implementation project(':lucene:lucene-core')
-  implementation project(':lucene:analysis:lucene-analyzers-common')
+  implementation project(':lucene:lucene-analyzers:lucene-analyzers-common')
   
   api ('org.apache.opennlp:opennlp-tools')
   
diff --git a/lucene/analysis/phonetic/build.gradle b/lucene/analysis/phonetic/build.gradle
index 1759ebd..63c311f 100644
--- a/lucene/analysis/phonetic/build.gradle
+++ b/lucene/analysis/phonetic/build.gradle
@@ -24,7 +24,7 @@ archivesBaseName = 'lucene-analyzers-phonetic'
 dependencies {
   
   implementation project(':lucene:lucene-core')
-  implementation project(':lucene:analysis:lucene-analyzers-common')
+  implementation project(':lucene:lucene-analyzers:lucene-analyzers-common')
   
   implementation ('commons-codec:commons-codec')
   
diff --git a/lucene/analysis/smartcn/build.gradle b/lucene/analysis/smartcn/build.gradle
index 7746a6e..be10486 100644
--- a/lucene/analysis/smartcn/build.gradle
+++ b/lucene/analysis/smartcn/build.gradle
@@ -24,7 +24,7 @@ archivesBaseName = 'lucene-analyzers-smartcn'
 dependencies {
   
   implementation project(':lucene:lucene-core')
-  implementation project(':lucene:analysis:lucene-analyzers-common')
+  implementation project(':lucene:lucene-analyzers:lucene-analyzers-common')
   
   testImplementation project(':lucene:lucene-test-framework')
 }
\ No newline at end of file
diff --git a/lucene/analysis/stempel/build.gradle b/lucene/analysis/stempel/build.gradle
index e2e77dd..62922ac 100644
--- a/lucene/analysis/stempel/build.gradle
+++ b/lucene/analysis/stempel/build.gradle
@@ -24,7 +24,7 @@ archivesBaseName = 'lucene-analyzers-stempel'
 dependencies {
   
   implementation project(':lucene:lucene-core')
-  implementation project(':lucene:analysis:lucene-analyzers-common')
+  implementation project(':lucene:lucene-analyzers:lucene-analyzers-common')
   
   testImplementation project(':lucene:lucene-test-framework')
 }
\ No newline at end of file
diff --git a/lucene/benchmark/build.gradle b/lucene/benchmark/build.gradle
index c61e108..8b44080 100644
--- a/lucene/benchmark/build.gradle
+++ b/lucene/benchmark/build.gradle
@@ -24,7 +24,7 @@ def workingDir = file("work")
 dependencies {
   
   implementation project(':lucene:lucene-core')
-  implementation project(':lucene:analysis:lucene-analyzers-common')
+  implementation project(':lucene:lucene-analyzers:lucene-analyzers-common')
   implementation project(':lucene:lucene-facet')
   implementation project(':lucene:lucene-highlighter')
   implementation project(':lucene:lucene-queries')
diff --git a/lucene/build.gradle b/lucene/build.gradle
index 0859631..289fc26 100644
--- a/lucene/build.gradle
+++ b/lucene/build.gradle
@@ -24,6 +24,8 @@ subprojects {
 
 def distDir = 'dist'
 
+ext.testsPolicy = "${rootDir}/lucene/tools/junit4/tests.policy"
+
 tasks.create('checkLicenses', LicenseCheckTask, file('licenses'))
 
 tasks.create('jarChecksums', JarChecksum, file('.'), file('licenses'))
diff --git a/lucene/classification/build.gradle b/lucene/classification/build.gradle
index 47e54e6..61baa7a 100644
--- a/lucene/classification/build.gradle
+++ b/lucene/classification/build.gradle
@@ -26,6 +26,6 @@ dependencies {
   implementation project(':lucene:lucene-grouping')
   
   testImplementation project(':lucene:lucene-test-framework')
-  testImplementation project(':lucene:analysis:lucene-analyzers-common')
+  testImplementation project(':lucene:lucene-analyzers:lucene-analyzers-common')
   testImplementation project(':lucene:lucene-codecs')
 }
diff --git a/lucene/demo/build.gradle b/lucene/demo/build.gradle
index 8b319ac..7143364 100644
--- a/lucene/demo/build.gradle
+++ b/lucene/demo/build.gradle
@@ -22,7 +22,7 @@ dependencies {
   implementation project(':lucene:lucene-core')
   implementation project(':lucene:lucene-facet')
   implementation project(':lucene:lucene-queries')
-  implementation project(':lucene:analysis:lucene-analyzers-common')
+  implementation project(':lucene:lucene-analyzers:lucene-analyzers-common')
   implementation project(':lucene:lucene-queryparser')
   implementation project(':lucene:lucene-expressions')
   
diff --git a/lucene/expressions/build.gradle b/lucene/expressions/build.gradle
index 003809e..1987bd8 100644
--- a/lucene/expressions/build.gradle
+++ b/lucene/expressions/build.gradle
@@ -20,11 +20,11 @@ apply plugin: 'maven-publish'
 apply plugin: org.apache.lucene.gradle.dist.PartOfDist
 
 dependencies {
-  
+  implementation project(':lucene:lucene-codecs')
   implementation project(':lucene:lucene-core')
   
-  testImplementation project(':lucene:lucene-test-framework')
-  
   implementation 'org.antlr:antlr4-runtime'
   implementation 'org.ow2.asm:asm-commons'
+
+  testImplementation project(':lucene:lucene-test-framework')
 }
diff --git a/lucene/highlighter/build.gradle b/lucene/highlighter/build.gradle
index 53f32c5..2ee6648 100644
--- a/lucene/highlighter/build.gradle
+++ b/lucene/highlighter/build.gradle
@@ -26,7 +26,7 @@ dependencies {
   implementation project(':lucene:lucene-memory')
   
   testImplementation project(':lucene:lucene-test-framework')
-  testImplementation project(':lucene:analysis:lucene-analyzers-common')
+  testImplementation project(':lucene:lucene-analyzers:lucene-analyzers-common')
 }
 
 ratSources {
diff --git a/lucene/luke/build.gradle b/lucene/luke/build.gradle
index 53af595..62c9562 100644
--- a/lucene/luke/build.gradle
+++ b/lucene/luke/build.gradle
@@ -23,7 +23,7 @@ dependencies {
   implementation project(':lucene:lucene-core')
   implementation project(':lucene:lucene-codecs')
   implementation project(':lucene:lucene-backward-codecs')
-  implementation project(':lucene:analysis:lucene-analyzers-common')
+  implementation project(':lucene:lucene-analyzers:lucene-analyzers-common')
   implementation project(':lucene:lucene-queries')
   implementation project(':lucene:lucene-queryparser')
   implementation project(':lucene:lucene-misc')
diff --git a/lucene/monitor/build.gradle b/lucene/monitor/build.gradle
index 067e110..964883b 100644
--- a/lucene/monitor/build.gradle
+++ b/lucene/monitor/build.gradle
@@ -21,7 +21,7 @@ apply plugin: org.apache.lucene.gradle.dist.PartOfDist
 
 dependencies {
   implementation project(':lucene:lucene-core')
-  implementation project(':lucene:analysis:lucene-analyzers-common')
+  implementation project(':lucene:lucene-analyzers:lucene-analyzers-common')
   implementation project(':lucene:lucene-queryparser')
   implementation project(':lucene:lucene-memory')
   
diff --git a/lucene/suggest/build.gradle b/lucene/suggest/build.gradle
index aca4389..fb7f0c9 100644
--- a/lucene/suggest/build.gradle
+++ b/lucene/suggest/build.gradle
@@ -21,7 +21,7 @@ apply plugin: org.apache.lucene.gradle.dist.PartOfDist
 
 dependencies {
   implementation project(':lucene:lucene-core')
-  implementation project(':lucene:analysis:lucene-analyzers-common')
+  implementation project(':lucene:lucene-analyzers:lucene-analyzers-common')
   
   testImplementation project(':lucene:lucene-test-framework')
 }
diff --git a/lucene/test-framework/build.gradle b/lucene/test-framework/build.gradle
index 89694bd..10f049a 100644
--- a/lucene/test-framework/build.gradle
+++ b/lucene/test-framework/build.gradle
@@ -19,12 +19,11 @@ apply plugin: 'java-library'
 apply plugin: 'maven-publish'
 apply plugin: org.apache.lucene.gradle.dist.PartOfDist
 
-archivesBaseName = 'lucene-test-framework'
-
 dependencies {
   
   implementation project(':lucene:lucene-core')
   implementation project(':lucene:lucene-codecs')
+  implementation project(':lucene:lucene-analyzers:lucene-analyzers-common')
   
   api ("junit:junit")
   api ('org.hamcrest:hamcrest-core')
diff --git a/settings.gradle b/settings.gradle
index cb8d672..ecb471b 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -7,113 +7,114 @@
  * in the user guide at https://docs.gradle.org/4.10.2/userguide/multi_project_builds.html
  */
 
-rootProject.name = '_lucene-solr'
-
 include 'buildSrc'
+include 'dev-tools'
 
-include 'lucene:analysis'
-project (':lucene:analysis').name='lucene-analysis'
-include 'lucene:analysis:common'
-project (':lucene:analysis:common').name='lucene-analyzers-common'
-include 'lucene:analysis:icu'
-project (':lucene:analysis:icu').name='lucene-analyzers-icu'
-include 'lucene:analysis:kuromoji'
-project (':lucene:analysis:kuromoji').name='lucene-analyzers-kuromoji'
-include 'lucene:analysis:morfologik'
-project (':lucene:analysis:morfologik').name='lucene-analyzers-morfologik'
-include 'lucene:analysis:nori'
-project (':lucene:analysis:nori').name='lucene-analyzers-nori'
-include 'lucene:analysis:opennlp'
-project (':lucene:analysis:opennlp').name='lucene-analyzers-opennlp'
-include 'lucene:analysis:phonetic'
-project (':lucene:analysis:phonetic').name='lucene-analyzers-phonetic'
-include 'lucene:analysis:smartcn'
-project (':lucene:analysis:smartcn').name='lucene-analyzers-smartcn'
-include 'lucene:analysis:stempel'
-project (':lucene:analysis:stempel').name='lucene-analyzers-stempel'
-include  'lucene:backward-codecs'
-project (':lucene:backward-codecs').name='lucene-backward-codecs'
-include  'lucene:benchmark'
-project (':lucene:benchmark').name='lucene-benchmark'
-include 'lucene:classification'
-project (':lucene:classification').name='lucene-classification'
-include 'lucene:codecs'
-project (':lucene:codecs').name='lucene-codecs'
-include 'lucene:core'
-project (':lucene:core').name='lucene-core'
-include 'lucene:demo'
-project (':lucene:demo').name='lucene-demo'
-include 'lucene:expressions'
-project (':lucene:expressions').name='lucene-expressions'
-include 'lucene:facet'
-project (':lucene:facet').name='lucene-facet'
-include 'lucene:grouping'
-project (':lucene:grouping').name='lucene-grouping'
-include 'lucene:highlighter'
-project (':lucene:highlighter').name='lucene-highlighter'
-include 'lucene:join'
-project (':lucene:join').name='lucene-join'
-include 'lucene:luke'
-project (':lucene:luke').name='lucene-luke'
-include 'lucene:memory'
-project (':lucene:memory').name='lucene-memory'
-include 'lucene:misc'
-project (':lucene:misc').name='lucene-misc'
-include 'lucene:monitor'
-project (':lucene:monitor').name='lucene-monitor'
-include 'lucene:queries'
-project (':lucene:queries').name='lucene-queries'
-include 'lucene:queryparser'
-project (':lucene:queryparser').name='lucene-queryparser'
-include 'lucene:replicator'
-project (':lucene:replicator').name='lucene-replicator'
-include 'lucene:sandbox'
-project (':lucene:sandbox').name='lucene-sandbox'
-include 'lucene:spatial'
-project (':lucene:spatial').name='lucene-spatial'
-include 'lucene:spatial-extras'
-project (':lucene:spatial-extras').name='lucene-spatial-extras'
-include 'lucene:spatial3d'
-project (':lucene:spatial3d').name='lucene-spatial3d'
-include 'lucene:suggest'
-project (':lucene:suggest').name='lucene-suggest'
-include 'lucene:test-framework'
-project (':lucene:test-framework').name='lucene-test-framework'
+include 'lucene'
+include 'lucene:lucene-core'
+project (':lucene:lucene-core').projectDir=file('lucene/core')
+include  'lucene:lucene-backward-codecs'
+project (':lucene:lucene-backward-codecs').projectDir=file('lucene/backward-codecs')
+include  'lucene:lucene-benchmark'
+project (':lucene:lucene-benchmark').projectDir=file('lucene/benchmark')
+include 'lucene:lucene-classification'
+project (':lucene:lucene-classification').projectDir=file('lucene/classification')
+include 'lucene:lucene-codecs'
+project (':lucene:lucene-codecs').projectDir=file('lucene/codecs')
+include 'lucene:lucene-demo'
+project (':lucene:lucene-demo').projectDir=file('lucene/demo')
+include 'lucene:lucene-expressions'
+project (':lucene:lucene-expressions').projectDir=file('lucene/expressions')
+include 'lucene:lucene-facet'
+project (':lucene:lucene-facet').projectDir=file('lucene/facet')
+include 'lucene:lucene-grouping'
+project (':lucene:lucene-grouping').projectDir=file('lucene/grouping')
+include 'lucene:lucene-highlighter'
+project (':lucene:lucene-highlighter').projectDir=file('lucene/highlighter')
+include 'lucene:lucene-join'
+project (':lucene:lucene-join').projectDir=file('lucene/join')
+include 'lucene:lucene-luke'
+project (':lucene:lucene-luke').projectDir=file('lucene/luke')
+include 'lucene:lucene-memory'
+project (':lucene:lucene-memory').projectDir=file('lucene/memory')
+include 'lucene:lucene-misc'
+project (':lucene:lucene-misc').projectDir=file('lucene/misc')
+include 'lucene:lucene-monitor'
+project (':lucene:lucene-monitor').projectDir=file('lucene/monitor')
+include 'lucene:lucene-queries'
+project (':lucene:lucene-queries').projectDir=file('lucene/queries')
+include 'lucene:lucene-queryparser'
+project (':lucene:lucene-queryparser').projectDir=file('lucene/queryparser')
+include 'lucene:lucene-replicator'
+project (':lucene:lucene-replicator').projectDir=file('lucene/replicator')
+include 'lucene:lucene-sandbox'
+project (':lucene:lucene-sandbox').projectDir=file('lucene/sandbox')
+include 'lucene:lucene-spatial'
+project (':lucene:lucene-spatial').projectDir=file('lucene/spatial')
+include 'lucene:lucene-spatial-extras'
+project (':lucene:lucene-spatial-extras').projectDir=file('lucene/spatial-extras')
+include 'lucene:lucene-spatial3d'
+project (':lucene:lucene-spatial3d').projectDir=file('lucene/spatial3d')
+include 'lucene:lucene-suggest'
+project (':lucene:lucene-suggest').projectDir=file('lucene/suggest')
+include 'lucene:lucene-test-framework'
+project (':lucene:lucene-test-framework').projectDir=file('lucene/test-framework')
+include 'lucene:lucene-analyzers'
+project (':lucene:lucene-analyzers').projectDir=file('lucene/analysis')
+include 'lucene:lucene-analyzers:lucene-analyzers-common'
+project (':lucene:lucene-analyzers:lucene-analyzers-common').projectDir=file('lucene/analysis/common')
+include 'lucene:lucene-analyzers:lucene-analyzers-icu'
+project (':lucene:lucene-analyzers:lucene-analyzers-icu').projectDir=file('lucene/analysis/icu')
+include 'lucene:lucene-analyzers:lucene-analyzers-kuromoji'
+project (':lucene:lucene-analyzers:lucene-analyzers-kuromoji').projectDir=file('lucene/analysis/kuromoji')
+include 'lucene:lucene-analyzers:lucene-analyzers-morfologik'
+project (':lucene:lucene-analyzers:lucene-analyzers-morfologik').projectDir=file('lucene/analysis/morfologik')
+include 'lucene:lucene-analyzers:lucene-analyzers-nori'
+project (':lucene:lucene-analyzers:lucene-analyzers-nori').projectDir=file('lucene/analysis/nori')
+include 'lucene:lucene-analyzers:lucene-analyzers-opennlp'
+project (':lucene:lucene-analyzers:lucene-analyzers-opennlp').projectDir=file('lucene/analysis/opennlp')
+include 'lucene:lucene-analyzers:lucene-analyzers-phonetic'
+project (':lucene:lucene-analyzers:lucene-analyzers-phonetic').projectDir=file('lucene/analysis/phonetic')
+include 'lucene:lucene-analyzers:lucene-analyzers-smartcn'
+project (':lucene:lucene-analyzers:lucene-analyzers-smartcn').projectDir=file('lucene/analysis/smartcn')
+include 'lucene:lucene-analyzers:lucene-analyzers-stempel'
+project (':lucene:lucene-analyzers:lucene-analyzers-stempel').projectDir=file('lucene/analysis/stempel')
 
-include 'solr:core'
-project (':solr:core').name='solr-core'
-include 'solr:server'
-project (':solr:server').name='solr-server'
-include 'solr:solrj'
-project (':solr:solrj').name='solr-solrj'
+include 'solr'
+include 'solr:solr-core'
+project (':solr:solr-core').projectDir=file('solr/core')
+include 'solr:solr-server'
+project (':solr:solr-server').projectDir=file('solr/server')
+include 'solr:solr-solrj'
+project (':solr:solr-solrj').projectDir=file('solr/solrj')
 include 'solr:solr-ref-guide'
-include 'solr:test-framework'
-project (':solr:test-framework').name='solr-test-framework'
-include 'solr:example'
-project (':solr:example').name='solr-example'
-include 'solr:example:example-DIH'
-project (':solr:example:example-DIH').name='solr-example-DIH'
-include 'solr:contrib'
-project (':solr:contrib').name='solr-contrib'
-include 'solr:contrib:analysis-extras'
-project (':solr:contrib:analysis-extras').name='solr-contrib-analysis-extras'
-include 'solr:contrib:analytics'
-project (':solr:contrib:analytics').name='solr-contrib-analytics'
-include 'solr:contrib:clustering'
-project (':solr:contrib:clustering').name='solr-contrib-clustering'
-include 'solr:contrib:dataimporthandler'
-project (':solr:contrib:dataimporthandler').name='solr-contrib-dataimporthandler'
-include 'solr:contrib:dataimporthandler-extras'
-project (':solr:contrib:dataimporthandler-extras').name='solr-contrib-dataimporthandler-extras'
-include 'solr:contrib:extraction'
-project (':solr:contrib:extraction').name='solr-contrib-extraction'
-include 'solr:contrib:langid'
-project (':solr:contrib:langid').name='solr-contrib-langid'
-include 'solr:contrib:ltr'
-project (':solr:contrib:ltr').name='solr-contrib-ltr'
-include 'solr:contrib:prometheus-exporter'
-project (':solr:contrib:prometheus-exporter').name='solr-contrib-prometheus-exporter'
-include 'solr:contrib:velocity'
-project (':solr:contrib:velocity').name='solr-contrib-velocity'
+include 'solr:solr-test-framework'
+project (':solr:solr-test-framework').projectDir=file('solr/test-framework')
+include 'solr:solr-example'
+project (':solr:solr-example').projectDir=file('solr/example')
+include 'solr:solr-example:solr-example-DIH'
+project (':solr:solr-example:solr-example-DIH').projectDir=file('solr/example/example-DIH')
+include 'solr:solr-contrib'
+project (':solr:solr-contrib').projectDir=file('solr/contrib')
+include 'solr:solr-contrib:solr-contrib-analysis-extras'
+project (':solr:solr-contrib:solr-contrib-analysis-extras').projectDir=file('solr/contrib/analysis-extras')
+include 'solr:solr-contrib:solr-contrib-analytics'
+project (':solr:solr-contrib:solr-contrib-analytics').projectDir=file('solr/contrib/analytics')
+include 'solr:solr-contrib:solr-contrib-clustering'
+project (':solr:solr-contrib:solr-contrib-clustering').projectDir=file('solr/contrib/clustering')
+include 'solr:solr-contrib:solr-contrib-dataimporthandler'
+project (':solr:solr-contrib:solr-contrib-dataimporthandler').projectDir=file('solr/contrib/dataimporthandler')
+include 'solr:solr-contrib:solr-contrib-dataimporthandler-extras'
+project (':solr:solr-contrib:solr-contrib-dataimporthandler-extras').projectDir=file('solr/contrib/dataimporthandler-extras')
+include 'solr:solr-contrib:solr-contrib-extraction'
+project (':solr:solr-contrib:solr-contrib-extraction').projectDir=file('solr/contrib/extraction')
+include 'solr:solr-contrib:solr-contrib-langid'
+project (':solr:solr-contrib:solr-contrib-langid').projectDir=file('solr/contrib/langid')
+include 'solr:solr-contrib:solr-contrib-ltr'
+project (':solr:solr-contrib:solr-contrib-ltr').projectDir=file('solr/contrib/ltr')
+include 'solr:solr-contrib:solr-contrib-prometheus-exporter'
+project (':solr:solr-contrib:solr-contrib-prometheus-exporter').projectDir=file('solr/contrib/prometheus-exporter')
+include 'solr:solr-contrib:solr-contrib-velocity'
+project (':solr:solr-contrib:solr-contrib-velocity').projectDir=file('solr/contrib/velocity')
+
 
-include 'dev-tools'
diff --git a/solr/build.gradle b/solr/build.gradle
index d247748..4c0a197 100644
--- a/solr/build.gradle
+++ b/solr/build.gradle
@@ -24,6 +24,8 @@ subprojects {
 
 def distDir = "dist"
 
+ext.testsPolicy = "${rootDir}/lucene/tools/junit4/solr-tests.policy"
+
 tasks.create("checkLicenses", LicenseCheckTask, file("licenses"))
 
 tasks.create("jarChecksums", JarChecksum, file('solr'), file('licenses'))
@@ -35,5 +37,5 @@ task packageDist(type: org.apache.lucene.gradle.dist.PackageLuceneSolrDist) {
   // additional includes for solr-server
   includeArtifacts '**/server/solr/**', '**/server/resources/**', '**/server/etc/**', '**/server/modules/**', '**/server/scripts/**', '**/server/contexts/**', '**/server/start.jar'
   
-  dependsOn project("solr-server").getStartJar
+  dependsOn { project(":solr:solr-server").getStartJar }
 }
diff --git a/solr/contrib/analysis-extras/build.gradle b/solr/contrib/analysis-extras/build.gradle
index 5c8dc15..9e18897 100644
--- a/solr/contrib/analysis-extras/build.gradle
+++ b/solr/contrib/analysis-extras/build.gradle
@@ -25,18 +25,18 @@ dependencies {
   implementation project(':solr:solr-core')
   implementation project(':lucene:lucene-core')
   implementation project(':lucene:lucene-codecs')
-  implementation project(':lucene:analysis:lucene-analyzers-icu')
-  implementation project(':lucene:analysis:lucene-analyzers-smartcn')
-  implementation project(':lucene:analysis:lucene-analyzers-morfologik')
-  implementation project(':lucene:analysis:lucene-analyzers-opennlp')
+  implementation project(':lucene:lucene-analyzers:lucene-analyzers-icu')
+  implementation project(':lucene:lucene-analyzers:lucene-analyzers-smartcn')
+  implementation project(':lucene:lucene-analyzers:lucene-analyzers-morfologik')
+  implementation project(':lucene:lucene-analyzers:lucene-analyzers-opennlp')
   
   implementation ('org.slf4j:slf4j-api')
   implementation ('commons-io:commons-io')
   implementation ('com.google.guava:guava')
   implementation ('commons-codec:commons-codec')
   
-  testImplementation project(path: ':lucene:analysis:lucene-analyzers-common', configuration: 'testOutput')
-  testImplementation project(path: ':solr:contrib:solr-contrib-dataimporthandler', configuration: 'testOutput')
+  testImplementation project(path: ':lucene:lucene-analyzers:lucene-analyzers-common', configuration: 'testOutput')
+  testImplementation project(path: ':solr:solr-contrib:solr-contrib-dataimporthandler', configuration: 'testOutput')
   testImplementation project(':lucene:lucene-test-framework')
   testImplementation project(':solr:solr-test-framework')
 
@@ -44,5 +44,5 @@ dependencies {
 
 missingDeps {
   addExclusionsFrom(project(':solr:solr-core')) // add solr-core exclusions
-  addExclusionsFrom(project(':lucene:analysis:lucene-analyzers-opennlp'))
+  addExclusionsFrom(project(':lucene:lucene-analyzers:lucene-analyzers-opennlp'))
 }
diff --git a/solr/contrib/analytics/build.gradle b/solr/contrib/analytics/build.gradle
index d2444a5..093b0b3 100644
--- a/solr/contrib/analytics/build.gradle
+++ b/solr/contrib/analytics/build.gradle
@@ -82,7 +82,7 @@ dependencies {
   testRuntimeOnly ('commons-io:commons-io')
   testRuntimeOnly ('org.slf4j:jcl-over-slf4j')
   
-  testRuntimeOnly project(':lucene:analysis:lucene-analyzers-common')
+  testRuntimeOnly project(':lucene:lucene-analyzers:lucene-analyzers-common')
   testRuntimeOnly project(':lucene:lucene-codecs')
   testRuntimeOnly project(':lucene:lucene-join')
   testRuntimeOnly project(':lucene:lucene-highlighter')
diff --git a/solr/contrib/clustering/build.gradle b/solr/contrib/clustering/build.gradle
index c89e698..fda5512 100644
--- a/solr/contrib/clustering/build.gradle
+++ b/solr/contrib/clustering/build.gradle
@@ -24,7 +24,7 @@ dependencies {
   implementation project(':solr:solr-core')
   implementation project(':solr:solr-solrj')
   implementation project(':lucene:lucene-core')
-  implementation project(':lucene:analysis:lucene-analyzers-common')
+  implementation project(':lucene:lucene-analyzers:lucene-analyzers-common')
   
   implementation ('org.slf4j:slf4j-api')
   implementation ('org.carrot2:carrot2-mini')
diff --git a/solr/contrib/dataimporthandler-extras/build.gradle b/solr/contrib/dataimporthandler-extras/build.gradle
index d660bf8..7b4545d 100644
--- a/solr/contrib/dataimporthandler-extras/build.gradle
+++ b/solr/contrib/dataimporthandler-extras/build.gradle
@@ -22,9 +22,9 @@ apply plugin: org.apache.lucene.gradle.dist.PartOfDist
 dependencies {
   implementation project(':solr:solr-core')
   implementation project(':solr:solr-solrj')
-  implementation project(':solr:contrib:solr-contrib-dataimporthandler')
-  implementation project(':lucene:analysis:lucene-analyzers-common')
-  implementation project(':solr:contrib:solr-contrib-extraction')
+  implementation project(':solr:solr-contrib:solr-contrib-dataimporthandler')
+  implementation project(':lucene:lucene-analyzers:lucene-analyzers-common')
+  implementation project(':solr:solr-contrib:solr-contrib-extraction')
   
   implementation ('org.slf4j:slf4j-api')
   implementation ('javax.activation:activation')
@@ -36,7 +36,7 @@ dependencies {
   implementation ('org.apache.tika:tika-core') { transitive = false }
   implementation ('org.apache.tika:tika-parsers') { transitive = false }
   
-  testImplementation project(path: ':solr:contrib:solr-contrib-dataimporthandler', configuration: 'testOutput')
+  testImplementation project(path: ':solr:solr-contrib:solr-contrib-dataimporthandler', configuration: 'testOutput')
   testImplementation project(':lucene:lucene-test-framework')
   testImplementation project(':solr:solr-test-framework')
 }
@@ -46,5 +46,5 @@ unusedDeps {
 }
 
 missingDeps {
-  addExclusionsFrom(project(':solr:contrib:solr-contrib-extraction'))
+  addExclusionsFrom(project(':solr:solr-contrib:solr-contrib-extraction'))
 }
diff --git a/solr/contrib/dataimporthandler/build.gradle b/solr/contrib/dataimporthandler/build.gradle
index 710ff82..1367425 100644
--- a/solr/contrib/dataimporthandler/build.gradle
+++ b/solr/contrib/dataimporthandler/build.gradle
@@ -37,7 +37,7 @@ dependencies {
   implementation project(':solr:solr-core')
   implementation project(':solr:solr-solrj')
   implementation project(':lucene:lucene-core')
-  implementation project(':lucene:analysis:lucene-analyzers-common')
+  implementation project(':lucene:lucene-analyzers:lucene-analyzers-common')
   implementation project(':lucene:lucene-join')
   
   implementation ('org.slf4j:slf4j-api')
diff --git a/solr/contrib/extraction/build.gradle b/solr/contrib/extraction/build.gradle
index d1baffd..08e97a2 100644
--- a/solr/contrib/extraction/build.gradle
+++ b/solr/contrib/extraction/build.gradle
@@ -25,7 +25,7 @@ dependencies {
   implementation project(':lucene:lucene-core')
   implementation project(':solr:solr-core')
   implementation project(':solr:solr-solrj')
-  implementation project(':lucene:analysis:lucene-analyzers-common')
+  implementation project(':lucene:lucene-analyzers:lucene-analyzers-common')
   
   implementation ('org.slf4j:slf4j-api')
   api ('org.apache.tika:tika-core') { transitive = false }
diff --git a/solr/contrib/langid/build.gradle b/solr/contrib/langid/build.gradle
index 4ece818..7dcdcc8 100644
--- a/solr/contrib/langid/build.gradle
+++ b/solr/contrib/langid/build.gradle
@@ -23,7 +23,7 @@ dependencies {
   implementation project(':solr:solr-core')
   implementation project(':solr:solr-solrj')
   implementation project(':lucene:lucene-core')
-  implementation project(':lucene:analysis:lucene-analyzers-common')
+  implementation project(':lucene:lucene-analyzers:lucene-analyzers-common')
   
   implementation 'com.cybozu.labs:langdetect'
   implementation 'net.arnx:jsonic'
@@ -40,5 +40,5 @@ dependencies {
 
 missingDeps {
   addExclusionsFrom(project(':solr:solr-core')) // add solr-core exclusions
-  addExclusionsFrom(project(':lucene:analysis:lucene-analyzers-opennlp'))
+  addExclusionsFrom(project(':lucene:lucene-analyzers:lucene-analyzers-opennlp'))
 }
diff --git a/solr/contrib/ltr/build.gradle b/solr/contrib/ltr/build.gradle
index 1080f13..3c98e71 100644
--- a/solr/contrib/ltr/build.gradle
+++ b/solr/contrib/ltr/build.gradle
@@ -24,13 +24,14 @@ dependencies {
   implementation project(':solr:solr-core')
   implementation project(':solr:solr-solrj')
   implementation project(':lucene:lucene-core')
-  implementation project(':lucene:analysis:lucene-analyzers-common')
+  implementation project(':lucene:lucene-analyzers:lucene-analyzers-common')
   
   implementation ('org.slf4j:slf4j-api')
   implementation ('org.restlet.jee:org.restlet')
   implementation ('commons-io:commons-io')
   implementation ('com.google.guava:guava')
   implementation ('commons-codec:commons-codec')
+  implementation ('org.eclipse.jetty:jetty-servlet')
   
   testRuntimeOnly ("org.slf4j:jcl-over-slf4j")
   
diff --git a/solr/contrib/prometheus-exporter/build.gradle b/solr/contrib/prometheus-exporter/build.gradle
index 7a18e65..2f45a7a 100644
--- a/solr/contrib/prometheus-exporter/build.gradle
+++ b/solr/contrib/prometheus-exporter/build.gradle
@@ -24,7 +24,7 @@ dependencies {
   implementation project(':solr:solr-core')
   implementation project(':solr:solr-solrj')
   implementation project(':lucene:lucene-core')
-  implementation project(':lucene:analysis:lucene-analyzers-common')
+  implementation project(':lucene:lucene-analyzers:lucene-analyzers-common')
   
   implementation ('io.prometheus:simpleclient')
   implementation ('io.prometheus:simpleclient_common')
diff --git a/solr/contrib/velocity/build.gradle b/solr/contrib/velocity/build.gradle
index b33ea53..03531e4 100644
--- a/solr/contrib/velocity/build.gradle
+++ b/solr/contrib/velocity/build.gradle
@@ -21,7 +21,7 @@ apply plugin: org.apache.lucene.gradle.dist.PartOfDist
 
 dependencies {
   
-  implementation project(':lucene:analysis:lucene-analyzers-common')
+  implementation project(':lucene:lucene-analyzers:lucene-analyzers-common')
   implementation project(':solr:solr-core')
   implementation project(':solr:solr-solrj')
   
diff --git a/solr/core/build.gradle b/solr/core/build.gradle
index dafed46..10fa975 100644
--- a/solr/core/build.gradle
+++ b/solr/core/build.gradle
@@ -25,12 +25,12 @@ archivesBaseName = 'solr-core'
 
 dependencies {
   
-  runtimeOnly project(':lucene:analysis:lucene-analyzers-phonetic')
+  runtimeOnly project(':lucene:lucene-analyzers:lucene-analyzers-phonetic')
   implementation project(':lucene:lucene-core')
   implementation project(':lucene:lucene-codecs')
-  implementation project(':lucene:analysis:lucene-analyzers-common')
-  implementation project(':lucene:analysis:lucene-analyzers-kuromoji')
-  implementation project(':lucene:analysis:lucene-analyzers-nori')
+  implementation project(':lucene:lucene-analyzers:lucene-analyzers-common')
+  implementation project(':lucene:lucene-analyzers:lucene-analyzers-kuromoji')
+  implementation project(':lucene:lucene-analyzers:lucene-analyzers-nori')
   implementation project(':lucene:lucene-suggest')
   implementation project(':lucene:lucene-queries')
   implementation project(':lucene:lucene-highlighter')
@@ -43,7 +43,11 @@ dependencies {
   implementation project(':lucene:lucene-misc')
   implementation project(':lucene:lucene-join')
   implementation project(':solr:solr-solrj')
-  implementation project(':solr:solr-server')
+  implementation ('org.eclipse.jetty:jetty-servlet')
+  implementation ('org.eclipse.jetty.http2:http2-server')
+  implementation ('org.eclipse.jetty.http2:http2-common')
+  implementation ('org.eclipse.jetty:jetty-rewrite')
+  implementation ('org.eclipse.jetty:jetty-alpn-server')
   
   // used for log4j2 async support
   runtimeOnly ('com.lmax:disruptor')
@@ -179,8 +183,8 @@ dependencies {
   testImplementation project(path: ':lucene:lucene-queryparser', configuration: 'testOutput')
   testImplementation project(':lucene:lucene-test-framework')
   testImplementation project(':solr:solr-test-framework')
-  testImplementation project(':lucene:analysis:lucene-analyzers-icu')
-  testImplementation project(':solr:contrib:solr-contrib-analysis-extras')
+  testImplementation project(':lucene:lucene-analyzers:lucene-analyzers-icu')
+  testImplementation project(':solr:solr-contrib:solr-contrib-analysis-extras')
   
 }
 
diff --git a/solr/server/build.gradle b/solr/server/build.gradle
index 086f1ac..fe8a02e 100644
--- a/solr/server/build.gradle
+++ b/solr/server/build.gradle
@@ -31,6 +31,9 @@ dependencies {
   runtimeOnly ('org.slf4j:jul-to-slf4j')
   runtimeOnly ('org.slf4j:slf4j-api')
   
+  runtimeOnly ('org.eclipse.jetty:jetty-alpn-java-server')
+  runtimeOnly ('org.eclipse.jetty:jetty-alpn-java-client')
+  
   implementation ('org.apache.logging.log4j:log4j-1.2-api')
   implementation ('org.apache.logging.log4j:log4j-api')
   implementation ('org.apache.logging.log4j:log4j-core')
@@ -41,28 +44,26 @@ dependencies {
   implementation ('io.dropwizard.metrics:metrics-jetty9')
   implementation ('io.dropwizard.metrics:metrics-jvm')
   
-  api ('org.eclipse.jetty:jetty-continuation')
-  api ('org.eclipse.jetty:jetty-deploy')
-  api ('org.eclipse.jetty:jetty-http')
-  api ('org.eclipse.jetty:jetty-io')
-  api ('org.eclipse.jetty:jetty-jmx')
-  api ('org.eclipse.jetty:jetty-rewrite')
-  api ('org.eclipse.jetty:jetty-security')
-  api ('org.eclipse.jetty:jetty-server')
-  api ('org.eclipse.jetty:jetty-servlet')
-  api ('org.eclipse.jetty:jetty-servlets')
-  api ('org.eclipse.jetty:jetty-util')
-  api ('org.eclipse.jetty:jetty-webapp')
-  api ('org.eclipse.jetty:jetty-xml')
-  runtimeOnly ('org.eclipse.jetty:jetty-alpn-java-server')
-  runtimeOnly ('org.eclipse.jetty:jetty-alpn-java-client')
-  api 'org.eclipse.jetty:jetty-alpn-server'
-  api 'org.eclipse.jetty:jetty-alpn-client'
+  implementation ('org.eclipse.jetty:jetty-continuation')
+  implementation ('org.eclipse.jetty:jetty-deploy')
+  implementation ('org.eclipse.jetty:jetty-http')
+  implementation ('org.eclipse.jetty:jetty-io')
+  implementation ('org.eclipse.jetty:jetty-jmx')
+  implementation ('org.eclipse.jetty:jetty-rewrite')
+  implementation ('org.eclipse.jetty:jetty-security')
+  implementation ('org.eclipse.jetty:jetty-server')
+  implementation ('org.eclipse.jetty:jetty-servlet')
+  implementation ('org.eclipse.jetty:jetty-servlets')
+  implementation ('org.eclipse.jetty:jetty-util')
+  implementation ('org.eclipse.jetty:jetty-webapp')
+  implementation ('org.eclipse.jetty:jetty-xml')
+  implementation 'org.eclipse.jetty:jetty-alpn-server'
+  implementation 'org.eclipse.jetty:jetty-alpn-client'
   
-  api ('org.eclipse.jetty.http2:http2-server')
-  api ('org.eclipse.jetty.http2:http2-common')
-  api ('org.eclipse.jetty.http2:http2-hpack')
-  api ('org.eclipse.jetty.http2:http2-http-client-transport')
+  implementation ('org.eclipse.jetty.http2:http2-server')
+  implementation ('org.eclipse.jetty.http2:http2-common')
+  implementation ('org.eclipse.jetty.http2:http2-hpack')
+  implementation ('org.eclipse.jetty.http2:http2-http-client-transport')
   
   implementation ('javax.servlet:javax.servlet-api')
   
diff --git a/solr/solrj/build.gradle b/solr/solrj/build.gradle
index 2f24e32..49ee834 100644
--- a/solr/solrj/build.gradle
+++ b/solr/solrj/build.gradle
@@ -59,8 +59,8 @@ dependencies {
   testImplementation project(':lucene:lucene-core')
   testImplementation project(':solr:solr-test-framework')
   testImplementation project(':lucene:lucene-test-framework')
-  testImplementation project(':lucene:analysis:lucene-analyzers-common')
-  testImplementation project(':solr:example:solr-example-DIH')
+  testImplementation project(':lucene:lucene-analyzers:lucene-analyzers-common')
+  testImplementation project(':solr:solr-example:solr-example-DIH')
 }
 
 missingDeps {
diff --git a/solr/test-framework/build.gradle b/solr/test-framework/build.gradle
index db3aa88..5642e7a 100644
--- a/solr/test-framework/build.gradle
+++ b/solr/test-framework/build.gradle
@@ -30,11 +30,13 @@ dependencies {
   api project(':lucene:lucene-core')
   api project(':lucene:lucene-codecs')
   api project(':lucene:lucene-queries')
-  api project(':lucene:analysis:lucene-analyzers-common')
+  api project(':lucene:lucene-analyzers:lucene-analyzers-common')
   api project(':lucene:lucene-test-framework')
   
   api ('junit:junit')
   api ('io.opentracing:opentracing-mock')
+
+  implementation ('org.eclipse.jetty:jetty-servlet')
   implementation ('commons-cli:commons-cli')
   implementation ('org.apache.httpcomponents:httpclient')
   implementation ('org.apache.httpcomponents:httpcore')
diff --git a/versions.lock b/versions.lock
index 3da6c4b..1f99e46 100644
--- a/versions.lock
+++ b/versions.lock
@@ -169,7 +169,7 @@ org.codehaus.jackson:jackson-xc:1.9.2 (1 constraints: da0befeb)
 org.codehaus.janino:commons-compiler:3.0.9 (2 constraints: d910f7d1)
 org.codehaus.janino:janino:3.0.9 (1 constraints: 0e050336)
 org.codehaus.jettison:jettison:1.1 (4 constraints: a84e24a9)
-org.codehaus.woodstox:stax2-api:3.1.4 (4 constraints: 7c331332)
+org.codehaus.woodstox:stax2-api:4.1 (4 constraints: 7c331332)
 org.codehaus.woodstox:woodstox-core-asl:4.4.1 (1 constraints: 0b050c36)
 org.eclipse.jetty:jetty-alpn-client:9.4.19.v20190610 (3 constraints: d12c8400)
 org.eclipse.jetty:jetty-alpn-java-client:9.4.19.v20190610 (1 constraints: 8007517d)