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/06/12 01:54:21 UTC

[lucene-solr] branch jira/SOLR-13452_gradle_3 updated: SOLR-13452: Finish making solr-core transitive and more work on the new dependency checkers. solr-core is now in compliance with these checkers.

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

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


The following commit(s) were added to refs/heads/jira/SOLR-13452_gradle_3 by this push:
     new 5898df1  SOLR-13452: Finish making solr-core transitive and more work on the new dependency checkers. solr-core is now in compliance with these checkers.
5898df1 is described below

commit 5898df1eed979df7fb2f0bd350c97d1f0e95f436
Author: markrmiller <ma...@apache.org>
AuthorDate: Tue Jun 11 20:54:03 2019 -0500

    SOLR-13452: Finish making solr-core transitive and more work on the new dependency checkers. solr-core is now in compliance with these checkers.
---
 build.gradle                                       |  27 ++---
 .../org/apache/lucene/gradle/JdepsReport.groovy    |  49 ++++----
 .../org/apache/lucene/gradle/MissingDeps.groovy    |  45 +++++--
 .../org/apache/lucene/gradle/UnusedDeps.groovy     |  57 +++++----
 solr/core/build.gradle                             | 135 ++++++++++-----------
 solr/solrj/build.gradle                            |   8 +-
 versions.lock                                      |  19 ++-
 7 files changed, 182 insertions(+), 158 deletions(-)

diff --git a/build.gradle b/build.gradle
index 9414fa4..cb60e43 100644
--- a/build.gradle
+++ b/build.gradle
@@ -39,8 +39,8 @@ allprojects {
   ext.filePath = { path -> file(path).getAbsolutePath() }
   // sugar multi part File
   ext.mfile = { file1, file2 -> new File(file(file1), file2.toString()) }
-  File target = File.createTempDir()
-  target.deleteOnExit()
+  File target = new File(System.getProperty("java.io.tmpdir") + '/lucene-solr-gradle')
+  //target.deleteOnExit()
   ext.tmp = target
   //gradle.buildFinished {delete(target)}
 }
@@ -186,41 +186,34 @@ configure(allprojects) {
     }
   }
   
+  File jdepsReportDir = mfile(project.buildDir, 'jdepsreport')
+  
+  task jdepsReport(type: org.apache.lucene.gradle.JdepsReport) {
+    target = jdepsReportDir
+  }
+  
   task listDependencies(type: org.apache.lucene.gradle.ListDeps) {
     group = 'Help'
     description = "List sorted dependencies and counts for a module."
   }
   
-  File jdepsReportDir = mfile(project.tmp, 'jdepsreport')
-  
   task unusedDependencies {
     group = 'Help'
     description = "Lists dependencies that may be unused for a module."
-
-    project.tasks.create("jdepsReport", org.apache.lucene.gradle.JdepsReport, jdepsReportDir, true)
     task unusedDeps(type: org.apache.lucene.gradle.UnusedDeps) {
       inputDirectory jdepsReportDir
     }
-    project.unusedDeps.dependsOn project.jdepsReport
-    project.unusedDeps.doLast {
-      delete(jdepsReportDir)
-    }
+    unusedDeps.dependsOn jdepsReport
     dependsOn unusedDeps
   }
   
   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)."
-    project.tasks.create("jdepsReportR", org.apache.lucene.gradle.JdepsReport, jdepsReportDir, true)
-    // we exclude hadoop and annotations
     task missingDeps(type: org.apache.lucene.gradle.MissingDeps) {
       inputDirectory jdepsReportDir
     }
-    
-    project.missingDeps.dependsOn project.jdepsReportR
-    project.missingDeps.doLast {
-      delete(jdepsReportDir)
-    }
+    missingDeps.dependsOn jdepsReport
     dependsOn missingDeps
   }
 }
diff --git a/buildSrc/src/main/groovy/org/apache/lucene/gradle/JdepsReport.groovy b/buildSrc/src/main/groovy/org/apache/lucene/gradle/JdepsReport.groovy
index f938cab..eff5719 100644
--- a/buildSrc/src/main/groovy/org/apache/lucene/gradle/JdepsReport.groovy
+++ b/buildSrc/src/main/groovy/org/apache/lucene/gradle/JdepsReport.groovy
@@ -38,7 +38,7 @@ import org.gradle.api.tasks.InputDirectory
 import org.gradle.api.tasks.InputFile
 import org.gradle.api.tasks.OutputDirectory
 import org.gradle.api.tasks.TaskAction
-
+import org.gradle.api.tasks.WorkResult
 import java.nio.file.Files
 import java.util.regex.Matcher
 import java.util.regex.Pattern
@@ -53,15 +53,13 @@ class JdepsReport extends DefaultTask {
   @OutputDirectory
   File target
   
+  @Optional
   @Input
-  boolean recursive
+  boolean recursive = true
 
-  @Inject
-  public JdepsReport(File target, boolean recursive) {
-    this.target = target
-    this.recursive = recursive
-    if (project.hasProperty('jdepsConfig')) {
-      configuration = project.jdepsConfig
+  public JdepsReport() {
+    if (project.hasProperty('useConfiguration')) {
+      configuration = project.useConfiguration
     }
     doFirst {
       println "Writing output files to ${target}"
@@ -88,7 +86,7 @@ class JdepsReport extends DefaultTask {
     // make sure ant task logging shows up by default
     ant.lifecycleLogLevel = "INFO"
     
-    project.copy {
+    WorkResult result = project.copy {
       into(distDir)
       
       Configuration config = project.configurations[this.configuration]
@@ -122,30 +120,33 @@ class JdepsReport extends DefaultTask {
       includeEmptyDirs = false
     }
     
-    runJdeps(getTopLvlProject(project), project, distDir, jdepsDir)
-    
-    Configuration config = project.configurations[this.configuration]
-    config.getAllDependencies().forEach({ dep ->
-      if (dep instanceof DefaultProjectDependency) {
-        Project dProject = dep.getDependencyProject()
-        def depTopLvlProject = getTopLvlProject(dProject)
-        
-        runJdeps(depTopLvlProject, dProject, distDir, jdepsDir)
-      }
-    })
+    if (result.getDidWork()) {
+      runJdeps(getTopLvlProject(project), project, project, distDir, jdepsDir)
+      
+      Configuration config = project.configurations[this.configuration]
+      config.getAllDependencies().forEach({ dep ->
+        if (dep instanceof DefaultProjectDependency) {
+          Project dProject = dep.getDependencyProject()
+          def depTopLvlProject = getTopLvlProject(dProject)
+          
+          runJdeps(depTopLvlProject, dProject, project, distDir, jdepsDir)
+        }
+      })
+    }
   }
   
-  protected void runJdeps(Project topLvlProject, Project project, File distDir, File jdepsDir) {
-    def distPath = "${distDir}/" + topLvlProject.name + "/" + topLvlProject.relativePath(project.projectDir)
+  protected void runJdeps(Project topLvlProject, Project project, Project libProject, File distDir, File jdepsDir) {
+    def distPath1 = "${distDir}/" + topLvlProject.name + "/" + topLvlProject.relativePath(libProject.projectDir)
+    def distPath2 = "${distDir}/" + topLvlProject.name + "/" + topLvlProject.relativePath(project.projectDir)
     def dotOutPath = jdepsDir.getAbsolutePath() + "/" + topLvlProject.name +  "/" + "${project.name}-${project.version}"
     
     ant.exec (executable: "jdeps", failonerror: true, resolveexecutable: true) {
-      ant.arg(line: '--class-path ' + "${distPath}/lib/" + '*')
+      ant.arg(line: '--class-path ' + "${distPath1}/lib/" + '*')
       ant.arg(line: '--multi-release 11')
       if (this.recursive) ant.arg(value: '-recursive')
       ant.arg(value: '-verbose:class')
       ant.arg(line: "-dotoutput ${dotOutPath}")
-      ant.arg(value: "${distPath}/${project.name}-${project.version}.jar")
+      ant.arg(value: "${distPath2}/${project.name}-${project.version}.jar")
     }
   }
   
diff --git a/buildSrc/src/main/groovy/org/apache/lucene/gradle/MissingDeps.groovy b/buildSrc/src/main/groovy/org/apache/lucene/gradle/MissingDeps.groovy
index 36039fc..0928fb9 100644
--- a/buildSrc/src/main/groovy/org/apache/lucene/gradle/MissingDeps.groovy
+++ b/buildSrc/src/main/groovy/org/apache/lucene/gradle/MissingDeps.groovy
@@ -34,7 +34,7 @@ import org.gradle.api.tasks.InputDirectory
 import org.gradle.api.tasks.InputFile
 import org.gradle.api.tasks.OutputDirectory
 import org.gradle.api.tasks.TaskAction
-
+import org.gradle.api.tasks.util.PatternSet
 import java.nio.file.Files
 import java.util.stream.Stream
 import java.util.concurrent.atomic.AtomicBoolean
@@ -51,13 +51,8 @@ class MissingDeps extends DefaultTask {
   @InputDirectory
   File inputDirectory
   
-  @Input
-  @Optional
-  List<String> depExcludes
-  
-  @Input
-  @Optional
-  List<String> classExcludes
+  private List<String> depExcludes = new ArrayList<>()
+  private List<String> classExcludes = new ArrayList<>()
   
   protected configuration = "runtimeClasspath"
   
@@ -81,7 +76,7 @@ class MissingDeps extends DefaultTask {
     File dotFile = project.mfile(inputDirectory, 'jdepsDir/' + topLvlProject.name +  "/" + "${project.name}-${project.version}/${project.name}-${project.version}.jar.dot")
     
     println ''
-    println 'Possibly missing deps:'
+    println 'Possibly missing deps (if the dot file is listed with no violations, it has violations that were excluded):'
     println ''
     
     boolean nothingFound = true
@@ -97,7 +92,7 @@ class MissingDeps extends DefaultTask {
     }.each {
       if (it.text.contains("(not found)")) {
         println ''
-        println it.name + ':'
+        println it.getParentFile().name + '/' + it.name + ':'
         
         String ourArtifactNameAndVersion = ''
         Matcher dotFileNameMatcher = dotFilePattern.matcher(it.name)
@@ -117,8 +112,10 @@ class MissingDeps extends DefaultTask {
               className = m.group(1)
               for (String classExclude : classExcludes) {
                 Matcher m2 = Pattern.compile(classExclude).matcher(className)
-                if (m2.find()) {
+                //println "${className} against ${classExclude}"
+                if (m2.matches()) {
                   excluded = true
+                  //println 'excluded'
                   break
                 }
               }
@@ -136,7 +133,33 @@ class MissingDeps extends DefaultTask {
     if (nothingFound) {
       println ''
       println 'No potential missing deps found!'
+    } else {
+      throw new GradleException("Missing dependencies found! Add them or add an exclusion if they are actually not necessary.")
+    }
+  }
+  
+  @Input
+  public Set<String> getClassExcludes() {
+    return classExcludes
+  }
+  
+  public MissingDeps classExclude(String... arg0) {
+    for (String pattern : arg0) {
+      classExcludes.add(pattern);
+    }
+    return this;
+  }
+  
+  @Input
+  public Set<String> getDepExcludes() {
+    return depExcludes
+  }
+  
+  public MissingDeps depExclude(String... arg0) {
+    for (String pattern : arg0) {
+      depExcludes.add(pattern);
     }
+    return this;
   }
   
   protected Project getTopLvlProject(Project proj) {
diff --git a/buildSrc/src/main/groovy/org/apache/lucene/gradle/UnusedDeps.groovy b/buildSrc/src/main/groovy/org/apache/lucene/gradle/UnusedDeps.groovy
index 45c1aba..a18d8c4 100644
--- a/buildSrc/src/main/groovy/org/apache/lucene/gradle/UnusedDeps.groovy
+++ b/buildSrc/src/main/groovy/org/apache/lucene/gradle/UnusedDeps.groovy
@@ -55,7 +55,7 @@ class UnusedDeps extends DefaultTask {
   
   @Input
   @Optional
-  List<String> jarExcludes
+  List<String> jarExcludes = new ArrayList<>()
   
   public UnusedDeps() {
     
@@ -133,7 +133,7 @@ class UnusedDeps extends DefaultTask {
     
     println ''
     println 'Our classpath dependency count ' + ourDepJarNames.size()
-    println 'Our directly used dependency count ' + usedStaticallyJarNames.size()
+    println 'Our directly declared dependency count ' + usedStaticallyJarNames.size()
     println ''
     println 'List of possibly unused jars - they may be used at runtime however (Class.forName on plugins or other dynamic Object instantiation for example). This is not definitive, but helps narrow down what to investigate.'
     println 'We take our classpath dependencies, substract our direct dependencies and then subtract dependencies used by our direct dependencies.'
@@ -146,6 +146,12 @@ class UnusedDeps extends DefaultTask {
     unusedJarNames.forEach({
       if (!depsInDirectUse.contains(it) && ourImmediatelyDefinedDeps.contains(it)) {
         
+        for (String exclude : jarExcludes) {
+          if (it.matches(exclude)) {
+            println  - 'excluded violation: ' + it
+            return
+          }
+        }
 
         if (findInSrc(it)) {
           println ' - ' + it + ' *'
@@ -158,7 +164,7 @@ class UnusedDeps extends DefaultTask {
     })
     
     println ''
-    println 'Deps brought in by other modules that may be unused in this module:'
+    println 'Deps brought in by other modules that may be unused in this module (this is expected to happen and mostly informational):'
     unusedJarNames.forEach({
       if (!depsInDirectUse.contains(it) && !ourImmediatelyDefinedDeps.contains(it)) {
         println ' - ' + it
@@ -234,34 +240,41 @@ class UnusedDeps extends DefaultTask {
   protected boolean findInSrc(String jarName) {
     AtomicBoolean foundInsrc = new AtomicBoolean(false)
     def files = project.configurations[configuration].resolvedConfiguration.getFiles()
-
-     Stream.of(files.toArray())
+    
+    Stream.of(files.toArray())
         .parallel()
         .forEach( { file ->
-      if (!file.name.equals(jarName)) return
-        try {
-          ZipFile zip = new ZipFile(file)
-          def entries = zip.entries()
-          entries.each { entry ->
-            if (!entry.isDirectory() && entry.getName().endsWith(".class") && !entry.getName().equals('module-info.class')) {
-              String className = entry.getName().replace('/', '.')
-              className = className.substring(0, className.length() - ".class".length())
-              
-              FindInSrc findInSrc = new FindInSrc()
-              def found = (findInSrc.find(project, jarName.substring(0, jarName.length() - ".jar".length()), className))
-              if (found) {
-                foundInsrc.set(true)
+          if (!file.name.equals(jarName)) return
+          try {
+            ZipFile zip = new ZipFile(file)
+            def entries = zip.entries()
+            entries.each { entry ->
+              if (!entry.isDirectory() && entry.getName().endsWith(".class") && !entry.getName().equals('module-info.class')) {
+                String className = entry.getName().replace('/', '.')
+                className = className.substring(0, className.length() - ".class".length())
+                
+                FindInSrc findInSrc = new FindInSrc()
+                def found = (findInSrc.find(project, jarName.substring(0, jarName.length() - ".jar".length()), className))
+                if (found) {
+                  foundInsrc.set(true)
+                }
               }
             }
+          } catch (ZipException zipEx) {
+            println "Unable to open file ${file.name}"
           }
-        } catch (ZipException zipEx) {
-          println "Unable to open file ${file.name}"
-        }
-    })
+        })
     
     return foundInsrc.get()
   }
   
+  public UnusedDeps jarExclude(String... arg0) {
+    for (String pattern : arg0) {
+      jarExcludes.add(pattern);
+    }
+    return this;
+  }
+  
   protected Project getTopLvlProject(Project proj) {
     def topLvlProject
     if (proj.group ==~ /.*?\.lucene(?:\.\w+)?/) {
diff --git a/solr/core/build.gradle b/solr/core/build.gradle
index b0adda1..a5a7b1d 100644
--- a/solr/core/build.gradle
+++ b/solr/core/build.gradle
@@ -46,28 +46,24 @@ dependencies {
   
   // used for log4j2 async support
   runtimeOnly ('com.lmax:disruptor')
+  runtimeOnly ('org.slf4j:log4j-over-slf4j') // bridge for deps that use log4j12 directly
+  runtimeOnly ('org.slf4j:jcl-over-slf4j') // bridge java common logging to slf4j
+  // TODO: this is not great, still have to work out logging dist strat
+  runtimeOnly ('org.apache.logging.log4j:log4j-slf4j-impl')
   
   // kerb, kerby, and curator deps used for security and auth with zk/hdfs/kerberos
-  runtimeOnly ('org.apache.curator:curator-recipes') {
-    exclude group: '*', module: '*' // brings in a lot we don't use
-  }
+  runtimeOnly ('org.apache.curator:curator-recipes') { transitive = false } // brings in a lot we don't use
   runtimeOnly ('org.apache.kerby:kerb-core')
   runtimeOnly ('org.apache.kerby:kerb-util')
   runtimeOnly ('org.apache.kerby:kerby-asn1')
   runtimeOnly ('org.apache.kerby:kerby-pkix')
   
   runtimeOnly ('com.google.protobuf:protobuf-java') // used by calicte.avatica
-  runtimeOnly ('org.slf4j:jcl-over-slf4j') // bridge java common logging to slf4j
   
   compileOnly ('javax.servlet:javax.servlet-api')
-  
-  // TODO: this is not great, still have to work out logging dist strat
-  implementation ('org.apache.logging.log4j:log4j-slf4j-impl')
 
   implementation ('org.slf4j:slf4j-api')
-  implementation ('org.apache.zookeeper:zookeeper') {
-    exclude group: '*', module: '*' // zk has many deps we don't need
-  }
+  implementation ('org.apache.zookeeper:zookeeper') { transitive = false } // brings in a lot we don't use
   implementation ('org.apache.httpcomponents:httpclient')
   implementation ('org.apache.httpcomponents:httpcore')
   implementation ('org.codehaus.woodstox:stax2-api')
@@ -86,9 +82,7 @@ dependencies {
   implementation ('commons-fileupload:commons-fileupload')
   implementation ('commons-cli:commons-cli')
   implementation ('org.apache.commons:commons-text')
-  implementation ('com.google.guava:guava') {
-    exclude group: '*', module: '*' // many annotation deps we don't need
-  }
+  implementation ('com.google.guava:guava') { transitive = false } // many annotation deps we don't need
   implementation ('org.locationtech.spatial4j:spatial4j')
   implementation ('org.apache.commons:commons-math3')
   implementation ('org.ow2.asm:asm')
@@ -98,48 +92,36 @@ dependencies {
   
   implementation ('org.apache.logging.log4j:log4j-api')
   implementation ('org.apache.logging.log4j:log4j-core')
-  implementation ('org.apache.logging.log4j:log4j-1.2-api')
   
   implementation ('com.fasterxml.jackson.core:jackson-core')
   implementation ('com.fasterxml.jackson.core:jackson-databind')
   implementation ('com.fasterxml.jackson.core:jackson-annotations')
   implementation ('com.fasterxml.jackson.dataformat:jackson-dataformat-smile')
-  implementation ('org.apache.hadoop:hadoop-auth') {
-    exclude group: '*', module: '*' // brings in a lot we don't use
-  }
-  implementation ('org.apache.hadoop:hadoop-common') {
-    exclude group: '*', module: '*' // brings in a lot we don't use
-  }
-  implementation ('org.apache.hadoop:hadoop-hdfs-client') {
-    exclude group: '*', module: '*' // brings in a lot we don't use
-  }
-  implementation ('org.apache.hadoop:hadoop-annotations') {
-    exclude group: '*', module: '*' // brings in a lot we don't use
-  }
+  implementation ('com.fasterxml.jackson.dataformat:jackson-dataformat-yaml') // added for calcite sql deps
+  
   implementation ('commons-collections:commons-collections')
   implementation ('com.github.ben-manes.caffeine:caffeine')
   implementation ('com.google.re2j:re2j')
   implementation ('org.apache.commons:commons-lang3')
   implementation ('org.apache.htrace:htrace-core4')
-  implementation ('org.apache.curator:curator-framework') {
-    exclude group: '*', module: '*' // brings in a lot we don't use
-  }
-  implementation ('org.apache.curator:curator-client')  {
-    exclude group: '*', module: '*' // brings in a lot we don't use
-  }
+  implementation ('org.apache.curator:curator-framework') { transitive = false } // brings in a lot we don't use
+  implementation ('org.apache.curator:curator-client') { transitive = false } // brings in a lot we don't use
+  implementation ('com.tdunning:t-digest')  // StatsComponents percentiles 
   
-  implementation ('com.tdunning:t-digest')
-  implementation ('org.apache.calcite:calcite-core') {
-    exclude group: '*', module: '*' // brings in a lot we don't use
-  }
-  implementation ('org.apache.calcite:calcite-linq4j') {
-    exclude group: '*', module: '*' // brings in a lot we don't use
-  }
-  implementation ('org.apache.calcite.avatica:avatica-core') {
-    exclude group: '*', module: '*' // brings in a lot we don't use
-  }
-  implementation ('org.apache.commons:commons-lang3')
+  // hdfs
+  implementation ('org.apache.hadoop:hadoop-auth') { transitive = false } // brings in a lot we don't use
+  implementation ('org.apache.hadoop:hadoop-common') { transitive = false } // brings in a lot we don't use
+  implementation ('org.apache.hadoop:hadoop-hdfs-client') { transitive = false } // brings in a lot we don't use
+  implementation ('org.apache.hadoop:hadoop-annotations') { transitive = false } // brings in a lot we don't use
+  
+  // sql parser
+  implementation ('org.apache.calcite:calcite-core') { transitive = false } // brings in a lot we don't use
+  implementation ('org.apache.calcite:calcite-linq4j') { transitive = false } // brings in a lot we don't use
+  implementation ('org.apache.calcite.avatica:avatica-core') { transitive = false } // brings in a lot we don't use
+  implementation ('org.codehaus.janino:janino')
   implementation ('org.codehaus.janino:commons-compiler')
+  implementation ('com.jayway.jsonpath:json-path')
+  implementation ('org.apache.commons:commons-lang3')
 
   implementation ('org.rrd4j:rrd4j')
   implementation ('org.bitbucket.b_c:jose4j')
@@ -155,7 +137,7 @@ dependencies {
   
   testImplementation ('org.restlet.jee:org.restlet.ext.servlet')
   
-  // kerby
+  // kerb, kerby, and curator deps used for security and auth with zk/hdfs/kerberos
   testRuntimeOnly ('org.apache.kerby:kerb-core')
   testRuntimeOnly ('org.apache.kerby:kerby-asn1')
   testRuntimeOnly ('org.apache.kerby:kerby-pkix')
@@ -167,31 +149,30 @@ dependencies {
   testRuntimeOnly ('org.apache.commons:commons-configuration2')
   
   testImplementation ('org.eclipse.jetty:jetty-xml')
-  testImplementation ('org.mockito:mockito-core') { transitive = false }
-  testImplementation ('net.bytebuddy:byte-buddy') { transitive = false }
-  testImplementation ('org.objenesis:objenesis') { transitive = false }
-  testImplementation ('commons-logging:commons-logging') { transitive = false }
-  testImplementation ('io.netty:netty-all') { transitive = false }
+  testImplementation ('org.mockito:mockito-core')
+  testImplementation ('net.bytebuddy:byte-buddy')
+  testImplementation ('org.objenesis:objenesis')
+  testImplementation ('commons-logging:commons-logging')
+  testImplementation ('io.netty:netty-all')
   testImplementation ('org.apache.commons:commons-text')
-  testImplementation ('org.eclipse.jetty:jetty-webapp') { transitive = false }
-  testImplementation ('com.sun.jersey:jersey-servlet:1.19.4') { transitive = false }
+  testImplementation ('org.eclipse.jetty:jetty-webapp')
+  testImplementation ('com.sun.jersey:jersey-servlet:1.19.4') { transitive = false } // brings in a lot we don't use
   
   // hdfs
-  testImplementation ('org.apache.hadoop:hadoop-minicluster') { transitive = false }
-  testImplementation ('org.apache.hadoop:hadoop-common::tests') { transitive = false }
-  testImplementation ('org.apache.hadoop:hadoop-hdfs') { transitive = false }
-  testImplementation ('org.apache.hadoop:hadoop-hdfs::tests') { transitive = false }
-  testImplementation ('org.apache.hadoop:hadoop-minikdc') { transitive = false }
+  testImplementation ('org.apache.hadoop:hadoop-common::tests') { transitive = false } // brings in a lot we don't use
+  testImplementation ('org.apache.hadoop:hadoop-hdfs') { transitive = false } // brings in a lot we don't use
+  testImplementation ('org.apache.hadoop:hadoop-hdfs::tests') { transitive = false } // brings in a lot we don't use
+  testImplementation ('org.apache.hadoop:hadoop-minikdc') { transitive = false } // brings in a lot we don't use
   testImplementation ('com.google.protobuf:protobuf-java')
   
   // kerby
-  testImplementation ('org.apache.kerby:kerb-client') { transitive = false }
-  testImplementation ('org.apache.kerby:kerb-common') { transitive = false }
-  testImplementation ('org.apache.kerby:kerb-identity') { transitive = false }
-  testImplementation ('org.apache.kerby:kerb-server') { transitive = false }
-  testImplementation ('org.apache.kerby:kerb-simplekdc') { transitive = false }
-  testImplementation ('org.apache.kerby:kerb-admin') { transitive = false }
-  testImplementation ('org.apache.kerby:kerby-kdc') { transitive = false }
+  testImplementation ('org.apache.kerby:kerb-client') { transitive = false } // brings in a lot we don't use
+  testImplementation ('org.apache.kerby:kerb-common') { transitive = false } // brings in a lot we don't use
+  testImplementation ('org.apache.kerby:kerb-identity') { transitive = false } // brings in a lot we don't use
+  testImplementation ('org.apache.kerby:kerb-server') { transitive = false } // brings in a lot we don't use
+  testImplementation ('org.apache.kerby:kerb-simplekdc') { transitive = false } // brings in a lot we don't use
+  testImplementation ('org.apache.kerby:kerb-admin') { transitive = false } // brings in a lot we don't use
+  testImplementation ('org.apache.kerby:kerby-kdc') { transitive = false } // brings in a lot we don't use
   
   testImplementation project(path: ':lucene:lucene-backward-codecs', configuration: 'testOutput')
   testImplementation project(path: ':lucene:lucene-queryparser', configuration: 'testOutput')
@@ -211,15 +192,25 @@ forbiddenApisTest {
   exclude 'org/apache/hadoop/**'
 }
 
-missingDeps() {
-  depExcludes = ['**/*hadoop*.dot'] // we exclude examining hadoop jars because we don't need lots of these deps
-  
-  classExcludes = [
-        'org\\.apache\\.yetus\\.audience\\.InterfaceAudience', // annotations jar
-        'javax\\.annotation\\..*', // annotations jar
-        'org\\.apache\\.yetus\\.audience', // annotations jar
-        'com\\.google\\.errorprone\\.annotations\\..*' // annotations jar
-      ]
+missingDeps {
+  depExclude  '**/*hadoop*.dot' // we exclude examining hadoop jars because we don't need lots of these deps
+  
+  classExclude 'org\\.apache\\.yetus\\.audience\\.InterfaceAudience.*' // annotations
+  classExclude 'javax\\.annotation\\..*' // annotations
+  classExclude 'com\\.google\\.errorprone\\.annotations\\..*' // annotations
+  classExclude 'org\\.fusesource\\.jansi\\..*' // log4j extra functionality we don't use
+  classExclude 'org\\.slf4j\\.ext\\.EventData' // log4j extra functionality we don't use
+  classExclude 'org\\.osgi\\.framework\\..*' // log4j osgi stuff we don't have
+  classExclude 'org\\.apache\\.log4j\\.jmx\\.HierarchyDynamicMBean' // zookeeper refs this log4j class directly
+  classExclude 'org\\.locationtech\\.jts\\..*' // spatial4j does not yet use jts
+  classExclude 'com\\.esri\\.core.geometry\\..*' // calcite sql stuff we appraently don't need
+  classExclude 'org\\.pentaho\\.aggdes\\..*'  // calcite sql stuff we apparently don't need
+  classExclude 'org\\.apache\\.commons\\.dbcp2\\.BasicDataSource' // calcite jdbc sql stuff we apparently don't need
+  classExclude 'com\\.yahoo\\.sketches\\.hll\\..*' // calcite sql stuff we apparently don't need
+}
+
+unusedDeps {
+  jarExclude 'kerby-pkix-.*?\\.jar'
 }
 
 task javacc(type: org.apache.lucene.gradle.SolrQPJavaCC) {
diff --git a/solr/solrj/build.gradle b/solr/solrj/build.gradle
index de44e2f..29172eb 100644
--- a/solr/solrj/build.gradle
+++ b/solr/solrj/build.gradle
@@ -21,9 +21,7 @@ apply plugin: org.apache.lucene.gradle.PartOfDist
 
 dependencies {
 
-  implementation ('org.apache.zookeeper:zookeeper') {
-    exclude group: '*', module: '*' // zk has many deps we don't need
-  }
+  implementation ('org.apache.zookeeper:zookeeper') { transitive = false } // // zk has annotation deps we don't need
   implementation ('org.apache.httpcomponents:httpclient')
   implementation ('org.apache.httpcomponents:httpmime')
   implementation ('org.apache.httpcomponents:httpcore')
@@ -44,9 +42,7 @@ dependencies {
   testImplementation ('org.eclipse.jetty:jetty-server')
   testImplementation ('org.eclipse.jetty:jetty-xml')
   testImplementation ('commons-collections:commons-collections')
-  testImplementation ('com.google.guava:guava') {
-    exclude group: '*', module: '*' // many annotation deps we don't need
-  }
+  testImplementation ('com.google.guava:guava') { transitive = false } // has many deps we don't need
   testImplementation ('org.apache.commons:commons-compress')
   testImplementation ('org.mockito:mockito-core')
   testImplementation ('net.bytebuddy:byte-buddy')
diff --git a/versions.lock b/versions.lock
index 56f6ca8..8b746f4 100644
--- a/versions.lock
+++ b/versions.lock
@@ -8,9 +8,10 @@ com.cybozu.labs:langdetect:1.1-20120112 (1 constraints: 5c066d5e)
 com.drewnoakes:metadata-extractor:2.11.0 (2 constraints: c011970f)
 com.epam:parso:2.0.9 (2 constraints: 6e11a9f2)
 com.fasterxml.jackson.core:jackson-annotations:2.9.8 (4 constraints: ad2e114a)
-com.fasterxml.jackson.core:jackson-core:2.9.8 (5 constraints: c4465e5f)
+com.fasterxml.jackson.core:jackson-core:2.9.8 (6 constraints: 6c5e8440)
 com.fasterxml.jackson.core:jackson-databind:2.9.8 (3 constraints: b21c2555)
 com.fasterxml.jackson.dataformat:jackson-dataformat-smile:2.9.8 (1 constraints: 15051836)
+com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.9.8 (1 constraints: 15051836)
 com.fasterxml.woodstox:woodstox-core:5.2.0 (1 constraints: 360a63bc)
 com.github.ben-manes.caffeine:caffeine:2.4.0 (1 constraints: 08050136)
 com.github.jai-imageio:jai-imageio-core:1.4.0 (1 constraints: 5c0ced01)
@@ -31,6 +32,7 @@ com.googlecode.mp4parser:isoparser:1.1.22 (2 constraints: c411d90f)
 com.healthmarketscience.jackcess:jackcess:2.1.12 (2 constraints: c411e10f)
 com.healthmarketscience.jackcess:jackcess-encrypt:2.1.4 (2 constraints: 661111f2)
 com.ibm.icu:icu4j:62.1 (1 constraints: dd040c31)
+com.jayway.jsonpath:json-path:2.4.0 (1 constraints: 08050136)
 com.jcraft:jsch:0.1.53 (1 constraints: 790ef15e)
 com.lmax:disruptor:3.4.0 (1 constraints: 09050636)
 com.pff:java-libpst:0.8.1 (2 constraints: 6a116bf2)
@@ -75,6 +77,8 @@ junit:junit:4.12 (2 constraints: 3e1e6104)
 net.arnx:jsonic:1.2.7 (2 constraints: db10d4d1)
 net.java.dev.jna:jna:4.3.0 (1 constraints: 5e0cf901)
 net.jcip:jcip-annotations:1.0 (5 constraints: 6824b237)
+net.minidev:accessors-smart:1.2 (1 constraints: e60926a4)
+net.minidev:json-smart:2.3 (1 constraints: a40c49ff)
 net.sf.ehcache:ehcache-core:2.6.2 (1 constraints: 2706f94d)
 net.sourceforge.argparse4j:argparse4j:0.8.1 (1 constraints: 0b050436)
 net.sourceforge.nekohtml:nekohtml:1.9.17 (1 constraints: 4405503b)
@@ -116,8 +120,8 @@ org.apache.kerby:kerby-config:1.0.1 (1 constraints: 860b05e6)
 org.apache.kerby:kerby-pkix:1.0.1 (2 constraints: 741065ca)
 org.apache.kerby:kerby-util:1.0.1 (2 constraints: 6518bdb6)
 org.apache.logging.log4j:log4j-1.2-api:2.11.2 (1 constraints: 3805343b)
-org.apache.logging.log4j:log4j-api:2.11.2 (4 constraints: c83394ae)
-org.apache.logging.log4j:log4j-core:2.11.2 (3 constraints: 102588ba)
+org.apache.logging.log4j:log4j-api:2.11.2 (3 constraints: c124e473)
+org.apache.logging.log4j:log4j-core:2.11.2 (2 constraints: 09164024)
 org.apache.logging.log4j:log4j-slf4j-impl:2.11.2 (1 constraints: 3805343b)
 org.apache.opennlp:opennlp-tools:1.9.1 (2 constraints: 6d11c4f2)
 org.apache.pdfbox:fontbox:2.0.15 (2 constraints: 4f1040c5)
@@ -165,7 +169,8 @@ org.carrot2.attributes:attributes-binder:1.3.3 (2 constraints: ab0f86a6)
 org.carrot2.shaded:carrot2-guava:18.0 (3 constraints: 8f202231)
 org.ccil.cowan.tagsoup:tagsoup:1.2.1 (2 constraints: 601198f1)
 org.checkerframework:checker-qual:2.0.0 (1 constraints: 140ae5b4)
-org.codehaus.janino:commons-compiler:3.0.9 (1 constraints: 0e050336)
+org.codehaus.janino:commons-compiler:3.0.9 (2 constraints: d910f7d1)
+org.codehaus.janino:janino:3.0.9 (1 constraints: 0e050336)
 org.codehaus.mojo:animal-sniffer-annotations:1.14 (1 constraints: ea09d5aa)
 org.codehaus.woodstox:stax2-api:4.1 (3 constraints: f125f836)
 org.codehaus.woodstox:woodstox-core-asl:4.4.1 (1 constraints: 0b050c36)
@@ -205,7 +210,7 @@ org.jsoup:jsoup:1.11.3 (2 constraints: c411dd0f)
 org.jvnet.staxex:stax-ex:1.7.8 (1 constraints: c50dc135)
 org.locationtech.spatial4j:spatial4j:0.7 (1 constraints: ab041e2c)
 org.opengis:geoapi:3.0.1 (7 constraints: 1361d046)
-org.ow2.asm:asm:6.2 (4 constraints: 2223c0a3)
+org.ow2.asm:asm:6.2 (5 constraints: 772fb0b6)
 org.ow2.asm:asm-analysis:6.2 (1 constraints: e309d6a5)
 org.ow2.asm:asm-commons:6.2 (1 constraints: aa04272c)
 org.ow2.asm:asm-tree:6.2 (2 constraints: 2d14228c)
@@ -215,8 +220,10 @@ org.rrd4j:rrd4j:3.5 (1 constraints: ac04252c)
 org.simpleframework:simple-xml:2.7.1 (3 constraints: bd20563c)
 org.slf4j:jcl-over-slf4j:1.7.25 (4 constraints: f629cf87)
 org.slf4j:jul-to-slf4j:1.7.25 (2 constraints: d5113e11)
-org.slf4j:slf4j-api:1.7.25 (23 constraints: a802e9ff)
+org.slf4j:log4j-over-slf4j:1.7.25 (1 constraints: 4005473b)
+org.slf4j:slf4j-api:1.7.25 (25 constraints: 251bf0a0)
 org.tallison:jmatio:1.5 (2 constraints: a810a0b8)
 org.tukaani:xz:1.8 (2 constraints: ae100fb9)
+org.yaml:snakeyaml:1.23 (1 constraints: 6e17f627)
 ua.net.nlp:morfologik-ukrainian-search:3.9.0 (1 constraints: 0e051536)
 xerces:xercesImpl:2.9.1 (1 constraints: 0e051136)