diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/jarfs/FastJarHandler.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/jarfs/FastJarHandler.kt index aab8cc5946a..4d8f907105e 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/jarfs/FastJarHandler.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/jarfs/FastJarHandler.kt @@ -4,12 +4,14 @@ */ package org.jetbrains.kotlin.cli.jvm.compiler.jarfs +import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.vfs.VirtualFile import java.io.File import java.io.FileNotFoundException import java.io.RandomAccessFile import java.nio.channels.FileChannel +import kotlin.collections.HashMap class FastJarHandler(val fileSystem: FastJarFileSystem, path: String) { private val myRoot: VirtualFile? @@ -25,7 +27,10 @@ class FastJarHandler(val fileSystem: FastJarFileSystem, path: String) { entries = try { mappedByteBuffer.parseCentralDirectory() } catch (e: Exception) { - throw IllegalStateException("Error while reading '${file.path}': $e", e) + // copying the behavior of ArchiveHandler (and therefore ZipHandler) + // TODO: consider propagating to compiler error or warning, but take into account that both javac and K1 simply ignore invalid jars in such cases + Logger.getInstance(this::class.java).warn("Error while reading zip file: ${file.path}: $e", e) + emptyList() } cachedManifest = entries.singleOrNull { StringUtil.equals(MANIFEST_PATH, it.relativePath) } diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/FastJarFSTest.kt b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/FastJarFSTest.kt index d2beda8cda5..4c81e8227de 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/FastJarFSTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/FastJarFSTest.kt @@ -5,12 +5,16 @@ package org.jetbrains.kotlin.jvm.compiler +import com.intellij.core.JavaCoreApplicationEnvironment +import com.intellij.openapi.util.Disposer import junit.framework.TestCase import org.jetbrains.kotlin.cli.jvm.compiler.jarfs.FastJarFileSystem import org.jetbrains.kotlin.test.KotlinTestUtils import org.junit.Assert +import java.io.ByteArrayOutputStream import java.io.File import java.io.FileOutputStream +import java.io.PrintStream import java.util.zip.ZipEntry import java.util.zip.ZipOutputStream @@ -18,13 +22,18 @@ import java.util.zip.ZipOutputStream class FastJarFSTest : TestCase() { private var fs: FastJarFileSystem? = null + private var coreAppEnv: JavaCoreApplicationEnvironment? = null + private val rootDisposable = Disposer.newDisposable() override fun setUp() { super.setUp() fs = FastJarFileSystem.createIfUnmappingPossible() + coreAppEnv = JavaCoreApplicationEnvironment(rootDisposable) } override fun tearDown() { + coreAppEnv = null + rootDisposable.dispose() fs?.clearHandlersCache() fs = null super.tearDown() @@ -57,4 +66,55 @@ class FastJarFSTest : TestCase() { Assert.assertEquals(String(file.contentsToByteArray()), i.toString()) } } + + fun testInvalidJar() { + val fs = fs ?: return + val tmpDir = KotlinTestUtils.tmpDirForTest(this) + val badJarFile = File(tmpDir, "file.pom") + badJarFile.writeText(A_POM_FILE) + + val errFromFastJarFs = captureErr { + fs.findFileByPath(badJarFile.absolutePath + "!/a.class") + } + Assert.assertTrue(errFromFastJarFs.contains("WARN: Error while reading zip file:")) + + val errFromCoreJarFs = captureErr { + coreAppEnv!!.jarFileSystem.findFileByPath(badJarFile.absolutePath + "!/a.class") + } + // Asserting that core jar FS still behaves the same way as the "emulation" implemented in FastJarFS + Assert.assertTrue(errFromCoreJarFs.contains("WARN: error in opening zip file")) + } } + +private fun captureErr(body: () -> Unit): String { + val outStream = ByteArrayOutputStream() + val prevErr = System.err + System.setErr(PrintStream(outStream)) + try { + body() + } + finally { + System.err.flush() + System.setErr(prevErr) + } + return outStream.toString() +} + +private const val A_POM_FILE = + """ + + 4.0.0 + a + b + 0.0.1 + pom + + + c + d + 0.0.1 + compile + + + +""" \ No newline at end of file