Better locking when getting classpath. Added more logging when there are problems.

This commit is contained in:
Robinson 2022-05-30 11:33:39 +02:00
parent 01d4fa1f80
commit b38d7838f7
No known key found for this signature in database
GPG Key ID: 8E7DB78588BD6F5C
3 changed files with 34 additions and 109 deletions

View File

@ -1,7 +1,7 @@
- GradleUtils - Gradle Plugin to manage various Gradle tasks, such as updating gradle and dependencies - GradleUtils - Gradle Plugin to manage various Gradle tasks, such as updating gradle and dependencies
[The Apache Software License, Version 2.0] [The Apache Software License, Version 2.0]
https://git.dorkbox.com/dorkbox/GradleUtils https://git.dorkbox.com/dorkbox/GradleUtils
Copyright 2021 Copyright 2022
Dorkbox LLC Dorkbox LLC
Extra license information Extra license information
@ -17,7 +17,7 @@
[The JSON License] [The JSON License]
https://github.com/stleary/JSON-java https://github.com/stleary/JSON-java
https://www.json.org/json-en.html https://www.json.org/json-en.html
Copyright 2021 Copyright 2022
JSON.org JSON.org
- Version - Java Semantic Versioning with exceptions. Minor/Patch number optional and build-after-final-dot (minor/patch) permitted. - Version - Java Semantic Versioning with exceptions. Minor/Patch number optional and build-after-final-dot (minor/patch) permitted.

View File

@ -34,7 +34,7 @@ object Extras {
// set for the project // set for the project
const val description = "Gradle Plugin to manage various Gradle tasks, such as updating gradle and dependencies" const val description = "Gradle Plugin to manage various Gradle tasks, such as updating gradle and dependencies"
const val group = "com.dorkbox" const val group = "com.dorkbox"
const val version = "2.16" const val version = "2.17"
// set as project.ext // set as project.ext
const val name = "Gradle Utils" const val name = "Gradle Utils"

View File

@ -21,16 +21,20 @@ import org.gradle.api.Project
import org.gradle.api.file.CopySpec import org.gradle.api.file.CopySpec
import org.gradle.api.tasks.TaskAction import org.gradle.api.tasks.TaskAction
import java.io.File import java.io.File
import java.util.concurrent.locks.ReentrantReadWriteLock
import kotlin.concurrent.read
import kotlin.concurrent.write
open class open class
PrepLibrariesTask : DefaultTask() { PrepLibrariesTask : DefaultTask() {
companion object { companion object {
private val lock = ReentrantReadWriteLock()
private val allLibraries = mutableMapOf<String, MutableMap<File, String>>() private val allLibraries = mutableMapOf<String, MutableMap<File, String>>()
private val allProjectLibraries = mutableMapOf<File, String>() private val allProjectLibraries = mutableMapOf<File, String>()
fun projectLibs(project: Project): MutableMap<File, String> { fun projectLibs(project: Project): MutableMap<File, String> {
synchronized(allLibraries) { lock.read {
val key = project.name val key = project.name
val map = allLibraries[key] val map = allLibraries[key]
@ -45,22 +49,23 @@ PrepLibrariesTask : DefaultTask() {
} }
fun collectLibraries(projects: Array<out Project>): Map<File, String> { fun collectLibraries(projects: Array<out Project>): Map<File, String> {
if (allProjectLibraries.isNotEmpty()) { lock.read {
return allProjectLibraries if (allProjectLibraries.isNotEmpty()) {
return allProjectLibraries
}
} }
println("\tCollecting all libraries for: ${projects.joinToString(",") { it.name }}") println("\tCollecting all libraries for: ${projects.joinToString(",") { it.name }}")
val librariesByFileName = mutableMapOf<String, File>() lock.write {
val librariesByFileName = mutableMapOf<String, File>()
synchronized(allProjectLibraries) {
projects.forEach { project -> projects.forEach { project ->
val tools = StaticMethodsAndTools(project) val tools = StaticMethodsAndTools(project)
collectLibs(tools, project, allProjectLibraries, librariesByFileName) collectLibs(tools, project, allProjectLibraries, librariesByFileName)
} }
}
return allProjectLibraries return allProjectLibraries
}
} }
fun copyLibrariesTo(projects: Array<out Project>): Action<CopySpec> { fun copyLibrariesTo(projects: Array<out Project>): Action<CopySpec> {
@ -170,7 +175,7 @@ PrepLibrariesTask : DefaultTask() {
val librariesByFileName = mutableMapOf<String, File>() val librariesByFileName = mutableMapOf<String, File>()
synchronized(projectLibs) { lock.write {
collectLibs(tools, project, projectLibs, librariesByFileName) collectLibs(tools, project, projectLibs, librariesByFileName)
} }
@ -192,19 +197,24 @@ PrepLibrariesTask : DefaultTask() {
val resolveAllDependencies = tools.resolveRuntimeDependencies(project).dependencies val resolveAllDependencies = tools.resolveRuntimeDependencies(project).dependencies
// we must synchronize on it for thread safety // we must synchronize on it for thread safety
synchronized(allLibraries) { lock.read {
resolveAllDependencies.forEach { dep -> resolveAllDependencies.forEach { dep ->
dep.artifacts.forEach { artifact -> dep.artifacts.forEach { artifact ->
val file = artifact.file val file = artifact.file
// get the file info from the reverse lookup, because we might have mangled the filename! // get the file info from the reverse lookup, because we might have mangled the filename!
val cacheFileName = projLibraries[file]!! val cacheFileName = projLibraries[file]
libraries[cacheFileName] = file if (cacheFileName == null) {
println("\tUnable to find: $file")
println("\\tExisting: ${projLibraries.map { it.key }.joinToString()}")
} else {
libraries[cacheFileName] = file
}
} }
} }
}
return libraries.keys.sorted().joinToString(prefix = "lib/", separator = " lib/", postfix = "\r\n") return libraries.keys.sorted().joinToString(prefix = "lib/", separator = " lib/", postfix = "\r\n")
}
} }
// NOTE: This must be referenced via a TASK, otherwise it will not work. // NOTE: This must be referenced via a TASK, otherwise it will not work.
@ -227,12 +237,10 @@ PrepLibrariesTask : DefaultTask() {
val projLibraries = collectLibraries() val projLibraries = collectLibraries()
println("\tCopying libraries for ${project.name}") println("\tCopying libraries for ${project.name}")
synchronized(projLibraries) { projLibraries.forEach { (file, fileName) ->
projLibraries.forEach { (file, fileName) -> copySpec.from(file) {
copySpec.from(file) { it.rename {
it.rename { fileName
fileName
}
} }
} }
} }
@ -246,92 +254,9 @@ PrepLibrariesTask : DefaultTask() {
val projLibraries = collectLibraries() val projLibraries = collectLibraries()
println("\tCopying libraries for ${project.name}") println("\tCopying libraries for ${project.name}")
synchronized(projLibraries) { projLibraries.forEach { (file, fileName) ->
projLibraries.forEach { (file, fileName) -> val newFile = location.resolve(fileName)
val newFile = location.resolve(fileName) file.copyTo(newFile, overwrite = true )
file.copyTo(newFile, overwrite = true )
}
} }
} }
} }
//
////////////////////
//// Build jars that are for "netref/teacherpanel".
//// NOTE: we cannot include bouncycastle in the jar -- because the bouncycastle jar is signed! (and it will screw up our jar, or not work)
//// NOTE: shadowjars DO NOT work (possibly because we rely on external jars. The "Class-Path" manifest value was ignored for some reason.
//// NOTE: OneJar/UnoJar/etc packaging solutions DO NOT work because VAADIN has terrible 'am i in a jar?' testing, which breaks when using this
//// we use shadowjar for screenshare/etc -- NOT FOR THE CORE SERVER OR FRONTEND
////////////////////
//
//val allLibrariesRev = mutableMapOf<File, String>()
//
//val prepLibraries = tasks.create("prepare_jar_libraries") {
// group = "$netrefgroupName support"
// RFC4519Style.description = "Prepares and checks the libraries used by all projects."
//
// outputs.cacheIf { false }
// outputs.upToDateWhen { false }
//
// // make sure all projects and subprojects are considered
// val recursion = LinkedList<Project>()
// val projects = mutableSetOf<Project>()
// recursion.add(rootProject)
//
// var next: Project
// while (recursion.isNotEmpty()) {
// next = recursion.poll()
// projects.add(next)
// recursion.addAll(next.subprojects)
// }
//
// val librariesByFileName = mutableMapOf<String, File>()
// synchronized(allLibrariesRev) {
// projects.forEach { subProject ->
// val resolveAllDependencies = resolveAllDependencies(subProject).flatMap { it.artifacts }
// resolveAllDependencies.forEach { artifact ->
// val file = artifact.file
// var fileName = file.name
//
// while (librariesByFileName.containsKey(fileName)) {
// // whoops! this is not good! Rename the file so it will be included. THIS PROBLEM ACTUALLY EXISTS, and is by accident!
// // if the target FILE is the same file (as the filename) then it's OK for this to be a duplicate
// if (file != librariesByFileName[fileName]) {
// val randomNum = (1..100).shuffled().first()
// fileName = "${file.nameWithoutExtension}_DUP_$randomNum.${file.extension}"
// println("\tTarget file exists already! Renaming to $fileName")
// } else {
// // the file name and path are the same, meaning this is just a duplicate library
// // instead of a DIFFERENT library with the same library file name.
// break
// }
// }
//
// // println("adding: " + file)
// librariesByFileName[fileName] = file
// allLibrariesRev[file] = fileName
// }
// }
// }
//}
//
//// get all jars needed on the library classpath, for RUNTIME (this is placed in the jar manifest)
//// NOTE: This must be referenced via a TASK, otherwise it will not work.
//fun getJarLibraryClasspath(project: Project): String {
// val libraries = mutableMapOf<String, File>()
//
// val resolveAllDependencies = resolveRuntimeDependencies(project).dependencies
// synchronized(allLibrariesRev) { // not actually USING "allLibraries", but we must synchronize on it for thread safety
// resolveAllDependencies.forEach { dep ->
// dep.artifacts.forEach { artifact ->
// val file = artifact.file
//
// // get the file info from the reverse lookup, because we might have mangled the filename!
// val cacheFileName = allLibrariesRev[file]!!
// libraries[cacheFileName] = file
// }
// }
// }
//
// return libraries.keys.sorted().joinToString(prefix = "lib/", separator = " lib/", postfix = "\r\n")
//}