diff --git a/generators/infrastructure/build-protobuf-lite.kts b/generators/infrastructure/build-protobuf-lite.kts new file mode 100644 index 00000000000..cebe6a332a1 --- /dev/null +++ b/generators/infrastructure/build-protobuf-lite.kts @@ -0,0 +1,87 @@ +package org.jetbrains.kotlin.infrastructure + +import java.io.BufferedOutputStream +import java.io.File +import java.io.FileOutputStream +import java.util.jar.JarEntry +import java.util.jar.JarFile +import java.util.zip.ZipOutputStream + +/** + * Strip away all unneeded classes from protobuf-java-*.jar to make a LITE version of the protobuf runtime. + * To do this, we load pom.xml from protobuf jar and heuristically extract information about which classes + * are kept in the lite runtime. + * (This could be done with actually parsing the XML, but this solution works just fine at the moment.) + * Then we take the full protobuf.jar and copy its contents to another jar, except those classes + * which are not needed in the lite runtime. + */ + +fun main(args: Array) { + val INCLUDE_START = "**/" + val INCLUDE_END = ".java" + val POM_PATH = "META-INF/maven/com.google.protobuf/protobuf-java/pom.xml" + + if (args.size() != 2) { + error("Usage: kotlinc -script build-protobuf-lite.kts ") + } + + val jarFile = File(args[0]) + val outputPath = args[1] + + assert(jarFile.exists()) { "protobuf jar not found at $jarFile" } + + fun loadAllFromJar(file: File): Map> { + val result = hashMapOf>() + val jar = JarFile(file) + try { + for (jarEntry in jar.entries()) { + result[jarEntry.getName()] = Pair(jarEntry, jar.getInputStream(jarEntry).readBytes()) + } + } + finally { + // Yes, JarFile does not extend Closeable on JDK 6 so we can't use "use" here + jar.close() + } + return result + } + + val allFiles = loadAllFromJar(jarFile) + + val keepClasses = arrayListOf() + + val pomBytes = allFiles[POM_PATH]?.second ?: error("pom.xml is not found in protobuf jar at $POM_PATH") + val lines = String(pomBytes).split("\n") + + var liteProfileReached = false + for (lineUntrimmed in lines) { + val line = lineUntrimmed.trim() + + if (liteProfileReached && line == "") { + break + } + else if (line == "lite") { + liteProfileReached = true + continue + } + + if (liteProfileReached && line.startsWith(INCLUDE_START) && line.endsWith(INCLUDE_END)) { + keepClasses.add(line.substringAfter(INCLUDE_START).substringBeforeLast(INCLUDE_END)) + } + } + + assert(liteProfileReached && keepClasses.isNotEmpty()) { "Wrong pom.xml or the format has changed, check its contents at $POM_PATH" } + + ZipOutputStream(BufferedOutputStream(FileOutputStream(File(outputPath)))).use { output -> + for ((name, value) in allFiles) { + val className = name.substringAfter("com/google/protobuf/").substringBeforeLast(".class") + if (keepClasses.any { className == it || className.startsWith(it + "$") }) { + val (entry, bytes) = value + output.putNextEntry(entry) + output.write(bytes) + output.closeEntry() + } + } + } +} + +main(args) diff --git a/update_dependencies.xml b/update_dependencies.xml index 747de73867a..54adcf7919d 100644 --- a/update_dependencies.xml +++ b/update_dependencies.xml @@ -279,6 +279,17 @@ + + + + + + + + + + + @@ -469,6 +480,8 @@ many nice features of IDEA including diffs in the test console. --> + +