Reduce use of temporary files

The Resource::compress method already holds entire files in memory at
once, as does the client-side loader. We might as well do the same on
the server-side.

Signed-off-by: Graham <gpe@openrs2.dev>
Graham 5 years ago
parent 0206bbd4b2
commit 2f3cdca12d
  1. 19
      asm/src/main/java/dev/openrs2/asm/io/Pack200LibraryReader.kt
  2. 21
      asm/src/main/java/dev/openrs2/asm/io/Pack200LibraryWriter.kt
  3. 28
      asm/src/main/java/dev/openrs2/asm/io/SignedJarLibraryWriter.kt
  4. 7
      crypto/src/main/java/dev/openrs2/crypto/Pkcs12KeyStore.kt

@ -2,31 +2,24 @@ package dev.openrs2.asm.io
import dev.openrs2.asm.classpath.Library
import dev.openrs2.compress.gzip.Gzip
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.InputStream
import java.nio.file.Files
import java.util.jar.JarOutputStream
import java.util.jar.Pack200
class Pack200LibraryReader : LibraryReader {
override fun read(input: InputStream): Library {
val temp = Files.createTempFile(TEMP_PREFIX, JAR_SUFFIX)
try {
ByteArrayOutputStream().use { tempOutput ->
Gzip.createHeaderlessInputStream(input).use { gzipInput ->
JarOutputStream(Files.newOutputStream(temp)).use { output ->
Pack200.newUnpacker().unpack(gzipInput, output)
JarOutputStream(tempOutput).use { jarOutput ->
Pack200.newUnpacker().unpack(gzipInput, jarOutput)
}
}
return Files.newInputStream(temp).use { tempInput ->
return ByteArrayInputStream(tempOutput.toByteArray()).use { tempInput ->
JarLibraryReader().read(tempInput)
}
} finally {
Files.deleteIfExists(temp)
}
}
private companion object {
private const val TEMP_PREFIX = "tmp"
private const val JAR_SUFFIX = ".jar"
}
}

@ -3,31 +3,22 @@ package dev.openrs2.asm.io
import dev.openrs2.asm.classpath.ClassPath
import dev.openrs2.asm.classpath.Library
import dev.openrs2.compress.gzip.Gzip
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.OutputStream
import java.nio.file.Files
import java.util.jar.JarInputStream
import java.util.jar.Pack200
class Pack200LibraryWriter : LibraryWriter {
override fun write(output: OutputStream, classPath: ClassPath, library: Library) {
val tempJar = Files.createTempFile(TEMP_PREFIX, JAR_SUFFIX)
try {
Files.newOutputStream(tempJar).use { tempOutput ->
ByteArrayOutputStream().use { tempOutput ->
JarLibraryWriter().write(tempOutput, classPath, library)
}
JarInputStream(Files.newInputStream(tempJar)).use { input ->
Gzip.createHeaderlessOutputStream(output).use { gzip ->
Pack200.newPacker().pack(input, gzip)
}
return JarInputStream(ByteArrayInputStream(tempOutput.toByteArray())).use { jarInput ->
Gzip.createHeaderlessOutputStream(output).use { gzipOutput ->
Pack200.newPacker().pack(jarInput, gzipOutput)
}
} finally {
Files.deleteIfExists(tempJar)
}
}
private companion object {
private const val TEMP_PREFIX = "tmp"
private const val JAR_SUFFIX = ".jar"
}
}

@ -5,9 +5,11 @@ import dev.openrs2.asm.classpath.Library
import dev.openrs2.crypto.Pkcs12KeyStore
import dev.openrs2.util.io.DeterministicJarOutputStream
import dev.openrs2.util.io.entries
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.InputStream
import java.io.OutputStream
import java.nio.file.Files
import java.nio.file.Path
import java.util.jar.JarInputStream
import java.util.jar.Manifest
@ -22,24 +24,24 @@ class SignedJarLibraryWriter(
ManifestJarLibraryWriter(manifest).write(unsignedOutput, classPath, library)
}
val signedJar = Files.createTempFile(TEMP_PREFIX, JAR_SUFFIX)
try {
keyStore.signJar(unsignedJar, signedJar)
repack(signedJar, output)
} finally {
Files.deleteIfExists(signedJar)
ByteArrayOutputStream().use { signedOutput ->
keyStore.signJar(unsignedJar, signedOutput)
return ByteArrayInputStream(signedOutput.toByteArray()).use { signedInput ->
repack(signedInput, output)
}
}
} finally {
Files.deleteIfExists(unsignedJar)
}
}
private fun repack(signedJar: Path, output: OutputStream) {
JarInputStream(Files.newInputStream(signedJar)).use { input ->
DeterministicJarOutputStream(output, input.manifest).use { output ->
for (entry in input.entries) {
output.putNextEntry(entry)
input.copyTo(output)
private fun repack(input: InputStream, output: OutputStream) {
JarInputStream(input).use { jarInput ->
DeterministicJarOutputStream(output, jarInput.manifest).use { jarOutput ->
for (entry in jarInput.entries) {
jarOutput.putNextEntry(entry)
jarInput.copyTo(jarOutput)
}
}
}

@ -11,6 +11,7 @@ import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter
import org.bouncycastle.crypto.util.SubjectPublicKeyInfoFactory
import org.bouncycastle.operator.bc.BcRSAContentSignerBuilder
import org.bouncycastle.util.BigIntegers
import java.io.OutputStream
import java.nio.file.Files
import java.nio.file.Path
import java.security.KeyFactory
@ -28,11 +29,9 @@ class Pkcs12KeyStore private constructor(privateKeyEntry: KeyStore.PrivateKeyEnt
.signerName(signerName)
.build()
fun signJar(input: Path, output: Path) {
fun signJar(input: Path, output: OutputStream) {
JarFile(input.toFile()).use { file ->
Files.newOutputStream(output).use { os ->
signer.sign(file, os)
}
signer.sign(file, output)
}
}

Loading…
Cancel
Save