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>
pull/105/head
Graham 4 years ago
parent 0206bbd4b2
commit 2f3cdca12d
  1. 19
      asm/src/main/java/dev/openrs2/asm/io/Pack200LibraryReader.kt
  2. 23
      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.asm.classpath.Library
import dev.openrs2.compress.gzip.Gzip import dev.openrs2.compress.gzip.Gzip
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.InputStream import java.io.InputStream
import java.nio.file.Files
import java.util.jar.JarOutputStream import java.util.jar.JarOutputStream
import java.util.jar.Pack200 import java.util.jar.Pack200
class Pack200LibraryReader : LibraryReader { class Pack200LibraryReader : LibraryReader {
override fun read(input: InputStream): Library { override fun read(input: InputStream): Library {
val temp = Files.createTempFile(TEMP_PREFIX, JAR_SUFFIX) ByteArrayOutputStream().use { tempOutput ->
try {
Gzip.createHeaderlessInputStream(input).use { gzipInput -> Gzip.createHeaderlessInputStream(input).use { gzipInput ->
JarOutputStream(Files.newOutputStream(temp)).use { output -> JarOutputStream(tempOutput).use { jarOutput ->
Pack200.newUnpacker().unpack(gzipInput, output) Pack200.newUnpacker().unpack(gzipInput, jarOutput)
} }
} }
return Files.newInputStream(temp).use { tempInput -> return ByteArrayInputStream(tempOutput.toByteArray()).use { tempInput ->
JarLibraryReader().read(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.ClassPath
import dev.openrs2.asm.classpath.Library import dev.openrs2.asm.classpath.Library
import dev.openrs2.compress.gzip.Gzip import dev.openrs2.compress.gzip.Gzip
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.OutputStream import java.io.OutputStream
import java.nio.file.Files
import java.util.jar.JarInputStream import java.util.jar.JarInputStream
import java.util.jar.Pack200 import java.util.jar.Pack200
class Pack200LibraryWriter : LibraryWriter { class Pack200LibraryWriter : LibraryWriter {
override fun write(output: OutputStream, classPath: ClassPath, library: Library) { override fun write(output: OutputStream, classPath: ClassPath, library: Library) {
val tempJar = Files.createTempFile(TEMP_PREFIX, JAR_SUFFIX) ByteArrayOutputStream().use { tempOutput ->
try { JarLibraryWriter().write(tempOutput, classPath, library)
Files.newOutputStream(tempJar).use { tempOutput ->
JarLibraryWriter().write(tempOutput, classPath, library)
}
JarInputStream(Files.newInputStream(tempJar)).use { input -> return JarInputStream(ByteArrayInputStream(tempOutput.toByteArray())).use { jarInput ->
Gzip.createHeaderlessOutputStream(output).use { gzip -> Gzip.createHeaderlessOutputStream(output).use { gzipOutput ->
Pack200.newPacker().pack(input, gzip) 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.crypto.Pkcs12KeyStore
import dev.openrs2.util.io.DeterministicJarOutputStream import dev.openrs2.util.io.DeterministicJarOutputStream
import dev.openrs2.util.io.entries import dev.openrs2.util.io.entries
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.InputStream
import java.io.OutputStream import java.io.OutputStream
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.Path
import java.util.jar.JarInputStream import java.util.jar.JarInputStream
import java.util.jar.Manifest import java.util.jar.Manifest
@ -22,24 +24,24 @@ class SignedJarLibraryWriter(
ManifestJarLibraryWriter(manifest).write(unsignedOutput, classPath, library) ManifestJarLibraryWriter(manifest).write(unsignedOutput, classPath, library)
} }
val signedJar = Files.createTempFile(TEMP_PREFIX, JAR_SUFFIX) ByteArrayOutputStream().use { signedOutput ->
try { keyStore.signJar(unsignedJar, signedOutput)
keyStore.signJar(unsignedJar, signedJar)
repack(signedJar, output) return ByteArrayInputStream(signedOutput.toByteArray()).use { signedInput ->
} finally { repack(signedInput, output)
Files.deleteIfExists(signedJar) }
} }
} finally { } finally {
Files.deleteIfExists(unsignedJar) Files.deleteIfExists(unsignedJar)
} }
} }
private fun repack(signedJar: Path, output: OutputStream) { private fun repack(input: InputStream, output: OutputStream) {
JarInputStream(Files.newInputStream(signedJar)).use { input -> JarInputStream(input).use { jarInput ->
DeterministicJarOutputStream(output, input.manifest).use { output -> DeterministicJarOutputStream(output, jarInput.manifest).use { jarOutput ->
for (entry in input.entries) { for (entry in jarInput.entries) {
output.putNextEntry(entry) jarOutput.putNextEntry(entry)
input.copyTo(output) jarInput.copyTo(jarOutput)
} }
} }
} }

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

Loading…
Cancel
Save