importMaven threadsafe set of written files

in case LocalMavenRepoDownloader is called from multiple threads at once

Bug: 268388000
Test: cherry-pick the following change that increases the number of writes to the set, and then run \
      `./development/importMaven/importMaven.sh com.android.tools.metalava:metalava:1.0.0-alpha07 --metalava-build-id=9581773 --redownload`
Change-Id: I0d0aacca33b9e57f55494b80ab418b9b26b420ee
diff --git a/development/importMaven/src/main/kotlin/androidx/build/importMaven/LocalMavenRepoDownloader.kt b/development/importMaven/src/main/kotlin/androidx/build/importMaven/LocalMavenRepoDownloader.kt
index cc106b9..57f1259 100644
--- a/development/importMaven/src/main/kotlin/androidx/build/importMaven/LocalMavenRepoDownloader.kt
+++ b/development/importMaven/src/main/kotlin/androidx/build/importMaven/LocalMavenRepoDownloader.kt
@@ -22,6 +22,7 @@
 import org.jetbrains.kotlin.com.google.common.annotations.VisibleForTesting
 import java.security.MessageDigest
 import java.util.Locale
+import java.util.concurrent.ConcurrentHashMap
 
 /**
  * A [DownloadObserver] that will save all files into the given repository folders.
@@ -39,12 +40,13 @@
 ) : DownloadObserver {
     private val logger = logger("LocalMavenRepoDownloader")
     private val licenseDownloader = LicenseDownloader(enableGithubApi = false)
-    private val writtenFiles = mutableSetOf<Path>()
+    private val writtenFilesMap: MutableMap<Path, Boolean> = ConcurrentHashMap<Path, Boolean>()
+    fun writtenFiles(): Set<Path> = writtenFilesMap.keys
 
     /**
      * Returns the list of files we've downloaded.
      */
-    fun getDownloadedFiles() = writtenFiles.sorted().distinct()
+    fun getDownloadedFiles() = writtenFiles()
 
     override fun onDownload(path: String, bytes: ByteArray) {
         if (path.substringAfterLast('.') in checksumExtensions) {
@@ -118,7 +120,7 @@
         file: Path,
         contents: ByteArray
     ) {
-        writtenFiles.add(file.normalized())
+        writtenFilesMap.put(file.normalized(), true)
         file.parent?.let(fileSystem::createDirectories)
         write(
             file = file,
@@ -144,7 +146,7 @@
      * might delete files that were resolved from the local repository.
      */
     fun cleanupLocalRepositories() {
-        val folders = writtenFiles.filter {
+        val folders = writtenFiles().filter {
             val isDirectory = fileSystem.metadata(it).isDirectory
             !isDirectory && it.name.substringAfterLast(".") in EXTENSIONS_FOR_CLENAUP
         }.mapNotNull {
@@ -160,7 +162,7 @@
                 "Cleaning up $folder ($index of ${folders.size})"
             }
             fileSystem.list(folder).forEach { candidateToDelete ->
-                if (!writtenFiles.contains(candidateToDelete.normalized())) {
+                if (!writtenFiles().contains(candidateToDelete.normalized())) {
                     logger.trace {
                         "Deleting $candidateToDelete since it is not re-downloaded"
                     }
@@ -255,4 +257,4 @@
             return signatureFileName to resultBytes
         }
     }
-}
\ No newline at end of file
+}