Skip to content

Commit 5bb10c3

Browse files
committed
Add collector API for multi-round transform
1 parent 854d5f7 commit 5bb10c3

File tree

5 files changed

+108
-4
lines changed

5 files changed

+108
-4
lines changed
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package com.didiglobal.booster.transform.util
2+
3+
import com.didiglobal.booster.kotlinx.search
4+
import com.didiglobal.booster.transform.TransformContext
5+
import org.apache.commons.compress.archivers.ArchiveEntry
6+
import org.apache.commons.compress.archivers.ArchiveStreamFactory
7+
import java.io.IOException
8+
9+
interface Collector<R> {
10+
fun accept(name: String): Boolean
11+
fun collect(name: String, data: () -> ByteArray): R
12+
}
13+
14+
sealed class Collectors {
15+
16+
object ClassNameCollector : Collector<String> {
17+
override fun accept(name: String): Boolean {
18+
return name.endsWith(".class", true)
19+
}
20+
21+
override fun collect(name: String, data: () -> ByteArray): String {
22+
return name.substringBeforeLast('.').replace('/', '.')
23+
}
24+
}
25+
26+
object ServiceCollector : Collector<Pair<String, Collection<String>>> {
27+
override fun accept(name: String): Boolean {
28+
return name.substringBeforeLast('/') == "META-INF/services"
29+
}
30+
31+
override fun collect(name: String, data: () -> ByteArray): Pair<String, Collection<String>> {
32+
return name.substringAfterLast('/').replace('/', '.') to data().inputStream().bufferedReader().lineSequence().filterNot {
33+
it.isBlank() || it.startsWith('#')
34+
}.toMutableSet()
35+
}
36+
}
37+
38+
}
39+
40+
fun <R> TransformContext.collect(collector: Collector<R>): List<R> = compileClasspath.map { file ->
41+
when {
42+
file.isDirectory -> {
43+
val base = file.toURI()
44+
file.search { f ->
45+
f.isFile && collector.accept(base.relativize(f.toURI()).normalize().path)
46+
}.map { f ->
47+
collector.collect(base.relativize(f.toURI()).normalize().path, f::readBytes)
48+
}
49+
}
50+
file.isFile -> {
51+
file.inputStream().buffered().use {
52+
ArchiveStreamFactory().createArchiveInputStream(it).let { archive ->
53+
generateSequence {
54+
try {
55+
archive.nextEntry
56+
} catch (e: IOException) {
57+
null
58+
}
59+
}.filterNot(ArchiveEntry::isDirectory).filter { entry ->
60+
collector.accept(entry.name)
61+
}.map { entry ->
62+
collector.collect(entry.name, archive::readBytes)
63+
}.toList()
64+
}
65+
}
66+
}
67+
else -> emptyList()
68+
}
69+
}.flatten()

booster-transform-util/src/main/kotlin/com/didiglobal/booster/transform/util/transform.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,14 +134,14 @@ fun ZipInputStream.transform(
134134
private const val DEFAULT_BUFFER_SIZE = 8 * 1024
135135

136136
private fun InputStream.readBytes(estimatedSize: Int = DEFAULT_BUFFER_SIZE): ByteArray {
137-
val buffer = ByteArrayOutputStream(estimatedSize.coerceAtLeast(this.available()))
137+
val buffer = ByteArrayOutputStream(maxOf(estimatedSize, this.available()))
138138
copyTo(buffer)
139139
return buffer.toByteArray()
140140
}
141141

142142
private fun InputStream.copyTo(out: OutputStream, bufferSize: Int = DEFAULT_BUFFER_SIZE): Long {
143143
var bytesCopied: Long = 0
144-
val buffer = ByteArray(bufferSize)
144+
val buffer = ByteArray(maxOf(bufferSize, this.available()))
145145
var bytes = read(buffer)
146146
while (bytes >= 0) {
147147
out.write(buffer, 0, bytes)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.didiglobal.booster.transform.util
2+
3+
import com.didiglobal.booster.transform.AbstractTransformContext
4+
import java.io.File
5+
import kotlin.test.Test
6+
import kotlin.test.assertEquals
7+
import kotlin.test.assertTrue
8+
9+
class CollectorTest {
10+
11+
@Test
12+
fun `collect class names from jar`() {
13+
val classpath = listOf(File(javaClass.classLoader.getResource("pinyin4j-2.5.0.jar")!!.file))
14+
val context = object : AbstractTransformContext("", "", emptyList(), classpath) {}
15+
val classes = context.collect(Collectors.ClassNameCollector)
16+
println(classes)
17+
assertTrue(classes.isNotEmpty())
18+
}
19+
20+
@Test
21+
fun `collect services from dir`() {
22+
val classpath = listOf(
23+
File(javaClass.protectionDomain.codeSource.location.file),
24+
File(javaClass.classLoader.getResource("pinyin4j-2.5.0.jar")!!.file).parentFile
25+
)
26+
val context = object : AbstractTransformContext("", "", emptyList(), classpath) {}
27+
val (api, impl) = context.collect(Collectors.ServiceCollector).single()
28+
assertEquals(api, Collector::class.java.name)
29+
assertEquals(2, impl.size)
30+
}
31+
32+
}

booster-transform-util/src/test/kotlin/com/didiglobal/booster/transform/util/FileTransformTest.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import kotlin.test.Test
88
import kotlin.test.assertEquals
99
import kotlin.test.assertTrue
1010

11-
private val PWD: String = System.getProperty("user.dir")
12-
private val BUILD_DIR = File(PWD, "build")
11+
internal val PWD: String = System.getProperty("user.dir")
12+
internal val BUILD_DIR = File(PWD, "build")
1313

1414
class FileTransformTest {
1515

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# This is a comment
2+
com.didiglobal.booster.transform.util.Collectors$ClassNameCollector
3+
com.didiglobal.booster.transform.util.Collectors$ServiceCollector

0 commit comments

Comments
 (0)