Fix "Deflater has been closed" error

This commit is contained in:
Koitharu
2024-11-23 13:14:19 +02:00
parent cffc6cfd39
commit 8a4bd9a19a

View File

@@ -5,6 +5,7 @@ import androidx.collection.ArraySet
import okhttp3.internal.closeQuietly import okhttp3.internal.closeQuietly
import okio.Closeable import okio.Closeable
import org.jetbrains.annotations.Blocking import org.jetbrains.annotations.Blocking
import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug
import org.koitharu.kotatsu.core.util.ext.withChildren import org.koitharu.kotatsu.core.util.ext.withChildren
import java.io.File import java.io.File
import java.io.FileInputStream import java.io.FileInputStream
@@ -13,6 +14,8 @@ import java.util.zip.Deflater
import java.util.zip.ZipEntry import java.util.zip.ZipEntry
import java.util.zip.ZipFile import java.util.zip.ZipFile
import java.util.zip.ZipOutputStream import java.util.zip.ZipOutputStream
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
class ZipOutput( class ZipOutput(
val file: File, val file: File,
@@ -21,6 +24,7 @@ class ZipOutput(
private val entryNames = ArraySet<String>() private val entryNames = ArraySet<String>()
private var cachedOutput: ZipOutputStream? = null private var cachedOutput: ZipOutputStream? = null
private var append: Boolean = false
@Blocking @Blocking
fun put(name: String, file: File): Boolean = withOutput { output -> fun put(name: String, file: File): Boolean = withOutput { output ->
@@ -77,7 +81,11 @@ class ZipOutput(
@Synchronized @Synchronized
override fun close() { override fun close() {
cachedOutput?.close() try {
cachedOutput?.close()
} catch (e: NullPointerException) {
e.printStackTraceDebug()
}
cachedOutput = null cachedOutput = null
} }
@@ -133,9 +141,21 @@ class ZipOutput(
@Synchronized @Synchronized
private fun <T> withOutput(block: (ZipOutputStream) -> T): T { private fun <T> withOutput(block: (ZipOutputStream) -> T): T {
val output = cachedOutput ?: newOutput(append = false) contract {
val res = block(output) callsInPlace(block, InvocationKind.AT_LEAST_ONCE)
output.flush() }
return try {
(cachedOutput ?: newOutput(append)).withOutputImpl(block).also {
append = true // after 1st success write
}
} catch (e: NullPointerException) { // probably NullPointerException: Deflater has been closed
newOutput(append).withOutputImpl(block)
}
}
private fun <T> ZipOutputStream.withOutputImpl(block: (ZipOutputStream) -> T): T {
val res = block(this)
flush()
return res return res
} }