Skip to content

Commit 50c7e5e

Browse files
jbarr21tschuchortdev
authored andcommitted
Fix decoding of classloader resources
* Fix decoding of classloader resources * Document internal method * Fix paths on Windows (cherry picked from commit 468101f)
1 parent 29a1e48 commit 50c7e5e

File tree

2 files changed

+38
-11
lines changed

2 files changed

+38
-11
lines changed

core/src/main/kotlin/com/tschuchort/compiletesting/AbstractKotlinCompilation.kt

+16-11
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import java.io.File
2121
import java.io.OutputStream
2222
import java.io.PrintStream
2323
import java.net.URI
24+
import java.net.URL
2425
import java.nio.file.Files
2526
import java.nio.file.Path
2627
import java.nio.file.Paths
@@ -62,8 +63,6 @@ abstract class AbstractKotlinCompilation<A : CommonCompilerArguments> internal c
6263
)
6364
var compilerPlugins: List<ComponentRegistrar> = emptyList()
6465

65-
66-
6766
/**
6867
* Legacy compiler plugins that should be added to the compilation.
6968
* This option will be removed in the future; you should migrate to [CompilerPluginRegistrar].
@@ -273,23 +272,26 @@ abstract class AbstractKotlinCompilation<A : CommonCompilerArguments> internal c
273272
}
274273

275274
protected fun getResourcesPath(): String {
276-
val resourceName = "META-INF/services/org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar"
277275
return this::class.java.classLoader.getResources(resourceName)
278276
.asSequence()
279-
.mapNotNull { url ->
280-
val uri = URI.create(url.toString().removeSuffix("/$resourceName"))
281-
when (uri.scheme) {
282-
"jar" -> Paths.get(URI.create(uri.rawSchemeSpecificPart.removeSuffix("!")))
283-
"file" -> Paths.get(uri)
284-
else -> return@mapNotNull null
285-
}.toAbsolutePath()
286-
}
277+
.mapNotNull { url -> urlToResourcePath(url) }
287278
.find { resourcesPath ->
288279
ServiceLoaderLite.findImplementations(CompilerPluginRegistrar::class.java, listOf(resourcesPath.toFile()))
289280
.any { implementation -> implementation == MainComponentAndPluginRegistrar::class.java.name }
290281
}?.toString() ?: throw AssertionError("Could not get path to CompilerPluginRegistrar service from META-INF")
291282
}
292283

284+
/** Maps a URL resource for a class from a JAR or file to an absolute Path on disk */
285+
internal fun urlToResourcePath(url: URL): Path? {
286+
val uri = url.toURI()
287+
val uriPath = when (uri.scheme) {
288+
"jar" -> uri.rawSchemeSpecificPart.removeSuffix("!/$resourceName")
289+
"file" -> uri.toString().removeSuffix("/$resourceName")
290+
else -> return null
291+
}
292+
return Paths.get(URI.create(uriPath)).toAbsolutePath()
293+
}
294+
293295
/** Searches compiler log for known errors that are hard to debug for the user */
294296
protected fun searchSystemOutForKnownErrors(compilerSystemOut: String) {
295297
if (compilerSystemOut.contains("No enum constant com.sun.tools.javac.main.Option.BOOT_CLASS_PATH")) {
@@ -340,8 +342,11 @@ abstract class AbstractKotlinCompilation<A : CommonCompilerArguments> internal c
340342
protected fun error(s: String) = internalMessageStream.println("error: $s")
341343

342344
internal val internalMessageStreamAccess: PrintStream get() = internalMessageStream
345+
346+
internal val resourceName = "META-INF/services/org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar"
343347
}
344348

349+
@ExperimentalCompilerApi
345350
internal fun convertKotlinExitCode(code: ExitCode) = when(code) {
346351
ExitCode.OK -> KotlinCompilation.ExitCode.OK
347352
ExitCode.INTERNAL_ERROR -> KotlinCompilation.ExitCode.INTERNAL_ERROR

core/src/test/kotlin/com/tschuchort/compiletesting/CompilerPluginsTest.kt

+22
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import org.junit.Assert
66
import org.junit.Ignore
77
import org.junit.Test
88
import org.mockito.Mockito
9+
import java.net.URL
910
import javax.annotation.processing.AbstractProcessor
1011
import javax.annotation.processing.RoundEnvironment
1112
import javax.lang.model.element.TypeElement
@@ -105,4 +106,25 @@ class CompilerPluginsTest {
105106
fakePlugin.assertRegistered()
106107
Assertions.assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK)
107108
}
109+
110+
@Test
111+
fun `convert jar url resource to path without decoding encoded path`() {
112+
// path on disk has "url%3Aport" path segment, but it's encoded from classLoader.getResources()
113+
val absolutePath = "jar:file:/path/to/jar/url%253Aport/core-0.4.0.jar!" +
114+
"/META-INF/services/org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar"
115+
val resultPath = KotlinCompilation().urlToResourcePath(URL(absolutePath)).toString()
116+
Assertions.assertThat(resultPath.contains("url:")).isFalse()
117+
Assertions.assertThat(resultPath.contains("url%25")).isFalse()
118+
Assertions.assertThat(resultPath.contains("url%3A")).isTrue()
119+
}
120+
121+
@Test
122+
fun `convert file url resource to path without decoding`() {
123+
// path on disk has "repos%3Aoss" path segment, but it's encoded from classLoader.getResources()
124+
val absolutePath = "file:/Users/user/repos%253Aoss/kotlin-compile-testing/core/build/resources/main"
125+
val resultPath = KotlinCompilation().urlToResourcePath(URL(absolutePath)).toString()
126+
Assertions.assertThat(resultPath.contains("repos:")).isFalse()
127+
Assertions.assertThat(resultPath.contains("repos%25")).isFalse()
128+
Assertions.assertThat(resultPath.contains("repos%3A")).isTrue()
129+
}
108130
}

0 commit comments

Comments
 (0)