From 5b7d56895b993437ef39a73734b271fcaf8ae513 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Tue, 27 Aug 2013 01:05:43 -0700 Subject: [PATCH] Provide accurate InputStream.available() results Provide accurate InputStream.available() results by using the size attribute of the ZipEntry. This helps improve performance with CGLib and also fixes issues where libraries expect that a non-zero result from available() indicates that read() will not return -1. --- .../boot/loader/jar/RandomAccessJarFile.java | 29 ++++++++++++++++--- .../loader/jar/RandomAccessJarFileTests.java | 2 ++ 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/RandomAccessJarFile.java b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/RandomAccessJarFile.java index 56d58f0756..07831eaecf 100644 --- a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/RandomAccessJarFile.java +++ b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/RandomAccessJarFile.java @@ -187,7 +187,7 @@ public class RandomAccessJarFile extends JarFile { public synchronized InputStream getInputStream(ZipEntry ze) throws IOException { InputStream inputStream = getData(ze).getInputStream(); if (ze.getMethod() == ZipEntry.DEFLATED) { - inputStream = new ZipInflaterInputStream(inputStream); + inputStream = new ZipInflaterInputStream(inputStream, (int) ze.getSize()); } return inputStream; } @@ -448,15 +448,35 @@ public class RandomAccessJarFile extends JarFile { } /** - * {@link InflaterInputStream} that support the writing of an extra "dummy" byte which - * is required with JDK 6 + * {@link InflaterInputStream} that supports the writing of an extra "dummy" byte + * (which is required with JDK 6) and returns accurate available() results. */ private static class ZipInflaterInputStream extends InflaterInputStream { private boolean extraBytesWritten; - public ZipInflaterInputStream(InputStream inputStream) { + private int available; + + public ZipInflaterInputStream(InputStream inputStream, int size) { super(inputStream, new Inflater(true), 512); + this.available = size; + } + + @Override + public int available() throws IOException { + if (this.available < 0) { + return super.available(); + } + return this.available; + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + int result = super.read(b, off, len); + if (result != -1) { + this.available -= result; + } + return result; } @Override @@ -476,4 +496,5 @@ public class RandomAccessJarFile extends JarFile { } } + } diff --git a/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/jar/RandomAccessJarFileTests.java b/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/jar/RandomAccessJarFileTests.java index 53fc06a576..e99fbebe43 100644 --- a/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/jar/RandomAccessJarFileTests.java +++ b/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/jar/RandomAccessJarFileTests.java @@ -115,7 +115,9 @@ public class RandomAccessJarFileTests { public void getInputStream() throws Exception { InputStream inputStream = this.jarFile.getInputStream(this.jarFile .getEntry("1.dat")); + assertThat(inputStream.available(), equalTo(1)); assertThat(inputStream.read(), equalTo(1)); + assertThat(inputStream.available(), equalTo(0)); assertThat(inputStream.read(), equalTo(-1)); }