diff --git a/src/main/kotlin/app/revanced/patcher/data/impl/ResourceData.kt b/src/main/kotlin/app/revanced/patcher/data/impl/ResourceData.kt index b5296f6a..6eebc45c 100644 --- a/src/main/kotlin/app/revanced/patcher/data/impl/ResourceData.kt +++ b/src/main/kotlin/app/revanced/patcher/data/impl/ResourceData.kt @@ -19,31 +19,66 @@ class ResourceData(private val resourceCacheDirectory: File) : Data, Iterable, + private val outputStream: Lazy? = null, ) : Closeable { + // path to the xml file to unlock the resource when closing the editor + private var filePath: String? = null + + /** + * The document of the xml file + */ val file: Document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputStream) .also(Document::normalize) // lazily open an output stream // this is required because when constructing a DomFileEditor the output stream is created along with the input stream, which is not allowed // the workaround is to lazily create the output stream. This way it would be used after the input stream is closed, which happens in the constructor - constructor(file: File) : this(file.inputStream(), lazy { file.outputStream() }) + constructor(file: File) : this(file.inputStream(), lazy { file.outputStream() }) { + filePath = file.path - override fun close() { - val result = StreamResult(outputStream.value) - TransformerFactory.newInstance().newTransformer().transform(DOMSource(file), result) + // prevent sharing mutability of the same file between multiple instances of DomFileEditor + if (locks.contains(filePath)) + throw IllegalStateException("Can not create a DomFileEditor for that file because it is already locked by another instance of DomFileEditor.") + locks.add(filePath!!) + } + override fun close() { inputStream.close() - outputStream.value.close() + + // if the output stream is not null, do not close it + outputStream?.let { + val result = StreamResult(it.value) + TransformerFactory.newInstance().newTransformer().transform(DOMSource(file), result) + + it.value.close() + } + + // remove the lock, if it exists + filePath?.let { + locks.remove(it) + } } + private companion object { + // list of locked file paths + val locks = mutableListOf() + } }