Add headerless bzip2 and gzip library

Signed-off-by: Graham <gpe@openrs2.dev>
Graham 5 years ago
parent a52d58e8b5
commit 892d21df10
  1. 2
      asm/build.gradle.kts
  2. 16
      asm/src/main/java/dev/openrs2/asm/classpath/Library.kt
  3. 1
      buildSrc/src/main/java/Versions.kt
  4. 25
      compress/build.gradle.kts
  5. 22
      compress/src/main/java/dev/openrs2/compress/bzip2/Bzip2.kt
  6. 21
      compress/src/main/java/dev/openrs2/compress/gzip/Gzip.kt
  7. 10
      compress/src/main/java/dev/openrs2/compress/gzip/GzipLevelOutputStream.kt
  8. 1
      settings.gradle.kts

@ -9,6 +9,8 @@ dependencies {
api("org.ow2.asm:asm-commons:${Versions.asm}") api("org.ow2.asm:asm-commons:${Versions.asm}")
api("org.ow2.asm:asm-tree:${Versions.asm}") api("org.ow2.asm:asm-tree:${Versions.asm}")
api("org.ow2.asm:asm-util:${Versions.asm}") api("org.ow2.asm:asm-util:${Versions.asm}")
implementation(project(":compress"))
} }
publishing { publishing {

@ -5,14 +5,12 @@ import dev.openrs2.asm.NopClassVisitor
import dev.openrs2.asm.remap import dev.openrs2.asm.remap
import dev.openrs2.common.crypto.Pkcs12KeyStore import dev.openrs2.common.crypto.Pkcs12KeyStore
import dev.openrs2.common.io.DeterministicJarOutputStream import dev.openrs2.common.io.DeterministicJarOutputStream
import dev.openrs2.common.io.SkipOutputStream import dev.openrs2.compress.gzip.Gzip
import org.objectweb.asm.ClassReader import org.objectweb.asm.ClassReader
import org.objectweb.asm.commons.Remapper import org.objectweb.asm.commons.Remapper
import org.objectweb.asm.tree.ClassNode import org.objectweb.asm.tree.ClassNode
import org.objectweb.asm.util.CheckClassAdapter import org.objectweb.asm.util.CheckClassAdapter
import java.io.ByteArrayInputStream
import java.io.OutputStream import java.io.OutputStream
import java.io.SequenceInputStream
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.Path import java.nio.file.Path
import java.util.TreeMap import java.util.TreeMap
@ -21,8 +19,6 @@ import java.util.jar.JarInputStream
import java.util.jar.JarOutputStream import java.util.jar.JarOutputStream
import java.util.jar.Manifest import java.util.jar.Manifest
import java.util.jar.Pack200 import java.util.jar.Pack200
import java.util.zip.GZIPInputStream
import java.util.zip.GZIPOutputStream
class Library constructor() : Iterable<ClassNode> { class Library constructor() : Iterable<ClassNode> {
private var classes = TreeMap<String, ClassNode>() private var classes = TreeMap<String, ClassNode>()
@ -120,9 +116,7 @@ class Library constructor() : Iterable<ClassNode> {
writeJar(classPath, temp) writeJar(classPath, temp)
JarInputStream(Files.newInputStream(temp)).use { `in` -> JarInputStream(Files.newInputStream(temp)).use { `in` ->
val headerSize = GZIP_HEADER.size.toLong() Gzip.createHeaderlessOutputStream(out).use { gzip ->
GZIPOutputStream(SkipOutputStream(out, headerSize)).use { gzip ->
Pack200.newPacker().pack(`in`, gzip) Pack200.newPacker().pack(`in`, gzip)
} }
} }
@ -140,7 +134,6 @@ class Library constructor() : Iterable<ClassNode> {
private const val CLASS_SUFFIX = ".class" private const val CLASS_SUFFIX = ".class"
private const val TEMP_PREFIX = "tmp" private const val TEMP_PREFIX = "tmp"
private const val JAR_SUFFIX = ".jar" private const val JAR_SUFFIX = ".jar"
private val GZIP_HEADER = byteArrayOf(0x1F, 0x8B.toByte())
fun readJar(path: Path): Library { fun readJar(path: Path): Library {
logger.info { "Reading jar $path" } logger.info { "Reading jar $path" }
@ -170,10 +163,7 @@ class Library constructor() : Iterable<ClassNode> {
val temp = Files.createTempFile(TEMP_PREFIX, JAR_SUFFIX) val temp = Files.createTempFile(TEMP_PREFIX, JAR_SUFFIX)
try { try {
val header = ByteArrayInputStream(GZIP_HEADER) Gzip.createHeaderlessInputStream(Files.newInputStream(path)).use { `in` ->
val data = Files.newInputStream(path)
GZIPInputStream(SequenceInputStream(header, data)).use { `in` ->
JarOutputStream(Files.newOutputStream(temp)).use { out -> JarOutputStream(Files.newOutputStream(temp)).use { out ->
Pack200.newUnpacker().unpack(`in`, out) Pack200.newUnpacker().unpack(`in`, out)
} }

@ -2,6 +2,7 @@ object Versions {
const val asm = "8.0" const val asm = "8.0"
const val bouncyCastle = "1.64" const val bouncyCastle = "1.64"
const val clikt = "2.6.0" const val clikt = "2.6.0"
const val commonsCompress = "1.20"
const val dependencyLicenseReport = "1.13" const val dependencyLicenseReport = "1.13"
const val fernflower = "1.0.3" const val fernflower = "1.0.3"
const val guava = "28.2-jre" const val guava = "28.2-jre"

@ -0,0 +1,25 @@
plugins {
`maven-publish`
kotlin("jvm")
}
dependencies {
implementation(project(":common"))
implementation("org.apache.commons:commons-compress:${Versions.commonsCompress}")
}
publishing {
publications.create<MavenPublication>("maven") {
from(components["java"])
pom {
packaging = "jar"
name.set("OpenRS2 Compression")
description.set(
"""
Provides headerless implementations of bzip2 and gzip.
""".trimIndent()
)
}
}
}

@ -0,0 +1,22 @@
package dev.openrs2.compress.bzip2
import dev.openrs2.common.io.SkipOutputStream
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream
import java.io.ByteArrayInputStream
import java.io.InputStream
import java.io.OutputStream
import java.io.SequenceInputStream
object Bzip2 {
private const val BLOCK_SIZE = 1
private val HEADER = byteArrayOf('B'.toByte(), 'Z'.toByte(), 'h'.toByte(), ('0' + BLOCK_SIZE).toByte())
fun createHeaderlessInputStream(input: InputStream): InputStream {
return BZip2CompressorInputStream(SequenceInputStream(ByteArrayInputStream(HEADER), input))
}
fun createHeaderlessOutputStream(output: OutputStream): OutputStream {
return BZip2CompressorOutputStream(SkipOutputStream(output, HEADER.size.toLong()), BLOCK_SIZE)
}
}

@ -0,0 +1,21 @@
package dev.openrs2.compress.gzip
import dev.openrs2.common.io.SkipOutputStream
import java.io.ByteArrayInputStream
import java.io.InputStream
import java.io.OutputStream
import java.io.SequenceInputStream
import java.util.zip.Deflater
import java.util.zip.GZIPInputStream
object Gzip {
private val HEADER = byteArrayOf(0x1F, 0x8B.toByte())
fun createHeaderlessInputStream(input: InputStream): InputStream {
return GZIPInputStream(SequenceInputStream(ByteArrayInputStream(HEADER), input))
}
fun createHeaderlessOutputStream(output: OutputStream, level: Int = Deflater.BEST_COMPRESSION): OutputStream {
return GzipLevelOutputStream(SkipOutputStream(output, HEADER.size.toLong()), level)
}
}

@ -0,0 +1,10 @@
package dev.openrs2.compress.gzip
import java.io.OutputStream
import java.util.zip.GZIPOutputStream
class GzipLevelOutputStream(output: OutputStream, level: Int) : GZIPOutputStream(output) {
init {
def.setLevel(level)
}
}

@ -7,6 +7,7 @@ include(
"asm", "asm",
"bundler", "bundler",
"common", "common",
"compress",
"decompiler", "decompiler",
"deob", "deob",
"deob-annotations", "deob-annotations",

Loading…
Cancel
Save