Skip to content

Instantly share code, notes, and snippets.

@squito
Created April 11, 2025 20:30
Show Gist options
  • Save squito/b00aeadefd79810e458cc9be664a9172 to your computer and use it in GitHub Desktop.
Save squito/b00aeadefd79810e458cc9be664a9172 to your computer and use it in GitHub Desktop.
Check for duplicate Jars on your classpath
import scala.util.matching.Regex
import collection.mutable. { HashMap, MultiMap, Set, HashSet}
/**
* Helper function, just to see if I got the regex correct
*/
def checkMatch(p: String, t: String): Option[Seq[String]] = {
p.r.findFirstMatchIn(t). map { m =>
(1 to m.groupCount).map { m.group(_) }
}
}
val jarVersionRegex = "(.*?)(-([0-9].*))?\\.jar".r
case class JarVersion(baseJar: String, version:Option[String], fullPath: String)
def extractJarVersion(fullPath: String): Option[JarVersion] = {
val file = fullPath.split("/").last
val matchOpt = jarVersionRegex.findFirstMatchIn(file)
matchOpt.map { m => JarVersion(m.group(1), Option(m.group(3)), fullPath) }
}
def findDupJars() = {
val mm = new HashMap [ String, Set[JarVersion]] with MultiMap [ String, JarVersion ]
val extractionFailed = new HashSet[String]()
val versionLessJars = new HashSet[JarVersion]()
sys.props("java.class.path").split(":").foreach { fullPath =>
extractJarVersion(fullPath) match {
case Some(jv) =>
mm.addBinding(jv.baseJar, jv)
if (jv.version == None) {
versionLessJars += jv
}
None // type inference seems confused otherwise :(
case None =>
extractionFailed += fullPath
None // type inference seems confused otherwise :(
}
}
println(s"${extractionFailed.size} CP entries failed regex match")
extractionFailed.foreach{ println }
println()
println()
println(s"${versionLessJars.size} CP entries have no version")
versionLessJars.foreach { println }
println()
println()
val dups = mm.filter { _._2.size > 1 }
println(s"${dups.size} CP entries have duplicate paths for same jar")
val dupsWithMultipleVersions = dups.map { case (base, versions) =>
base -> versions.flatMap { _.version }.toSet
}.filter { _._2.size > 1 }
println(s"${dupsWithMultipleVersions.size} jars have multiple versions on CP")
dupsWithMultipleVersions.foreach { case (base, versions) =>
println(s"$base -> $versions")
}
(extractionFailed, mm)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment