mirror of https://github.com/jwtk/jjwt.git
Refactored DeflateCompressionCodec to eliminate memory leak. Refactored GzipCompressionCodec and AbstractCompressionCodec to utilize consistent logic across compression algorithms. Resolves #392.
This commit is contained in:
parent
1b5b89304a
commit
af72fabbf3
|
@ -1,10 +1,14 @@
|
||||||
## Release Notes
|
## Release Notes
|
||||||
|
|
||||||
|
### 0.10.7
|
||||||
|
|
||||||
|
This patch release fixes a [memory leak](https://github.com/jwtk/jjwt/issues/392) found in the DEFLATE compression
|
||||||
|
codec implementation.
|
||||||
|
|
||||||
### 0.10.6
|
### 0.10.6
|
||||||
|
|
||||||
This patch release updates the jackson-databind version to 2.9.8 to address a critical security vulnerability in that
|
This patch release updates the jackson-databind version to 2.9.8 to address a critical security vulnerability in that
|
||||||
library. It also updates .travis.yml to remove deprecated builds and to "trick" travis into building with Oracle
|
library.
|
||||||
JDK 1.7 as this library still supports that Java version even if Travis no longer does.
|
|
||||||
|
|
||||||
### 0.10.5
|
### 0.10.5
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,12 @@ package io.jsonwebtoken.impl.compression;
|
||||||
import io.jsonwebtoken.CompressionCodec;
|
import io.jsonwebtoken.CompressionCodec;
|
||||||
import io.jsonwebtoken.CompressionException;
|
import io.jsonwebtoken.CompressionException;
|
||||||
import io.jsonwebtoken.lang.Assert;
|
import io.jsonwebtoken.lang.Assert;
|
||||||
|
import io.jsonwebtoken.lang.Objects;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract class that asserts arguments and wraps IOException with CompressionException.
|
* Abstract class that asserts arguments and wraps IOException with CompressionException.
|
||||||
|
@ -28,6 +32,44 @@ import java.io.IOException;
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractCompressionCodec implements CompressionCodec {
|
public abstract class AbstractCompressionCodec implements CompressionCodec {
|
||||||
|
|
||||||
|
//package-protected for a point release. This can be made protected on a minor release (0.11.0, 0.12.0, 1.0, etc).
|
||||||
|
//TODO: make protected on a minor release
|
||||||
|
interface StreamWrapper {
|
||||||
|
OutputStream wrap(OutputStream out) throws IOException;
|
||||||
|
}
|
||||||
|
|
||||||
|
//package-protected for a point release. This can be made protected on a minor release (0.11.0, 0.12.0, 1.0, etc).
|
||||||
|
//TODO: make protected on a minor release
|
||||||
|
byte[] readAndClose(InputStream input) throws IOException {
|
||||||
|
byte[] buffer = new byte[512];
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream(buffer.length);
|
||||||
|
int read;
|
||||||
|
try {
|
||||||
|
read = input.read(buffer); //assignment separate from loop invariant check for code coverage checks
|
||||||
|
while (read != -1) {
|
||||||
|
out.write(buffer, 0, read);
|
||||||
|
read = input.read(buffer);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
Objects.nullSafeClose(input);
|
||||||
|
}
|
||||||
|
return out.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
//package-protected for a point release. This can be made protected on a minor release (0.11.0, 0.12.0, 1.0, etc).
|
||||||
|
//TODO: make protected on a minor release
|
||||||
|
byte[] writeAndClose(byte[] payload, StreamWrapper wrapper) throws IOException {
|
||||||
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(512);
|
||||||
|
OutputStream compressionStream = wrapper.wrap(outputStream);
|
||||||
|
try {
|
||||||
|
compressionStream.write(payload);
|
||||||
|
compressionStream.flush();
|
||||||
|
} finally {
|
||||||
|
Objects.nullSafeClose(compressionStream);
|
||||||
|
}
|
||||||
|
return outputStream.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implement this method to do the actual work of compressing the payload
|
* Implement this method to do the actual work of compressing the payload
|
||||||
*
|
*
|
||||||
|
|
|
@ -15,13 +15,11 @@
|
||||||
*/
|
*/
|
||||||
package io.jsonwebtoken.impl.compression;
|
package io.jsonwebtoken.impl.compression;
|
||||||
|
|
||||||
import io.jsonwebtoken.lang.Objects;
|
import java.io.ByteArrayInputStream;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.zip.Deflater;
|
import java.io.OutputStream;
|
||||||
import java.util.zip.DeflaterOutputStream;
|
import java.util.zip.DeflaterOutputStream;
|
||||||
import java.util.zip.InflaterOutputStream;
|
import java.util.zip.InflaterInputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Codec implementing the <a href="https://en.wikipedia.org/wiki/DEFLATE">deflate compression algorithm</a>.
|
* Codec implementing the <a href="https://en.wikipedia.org/wiki/DEFLATE">deflate compression algorithm</a>.
|
||||||
|
@ -32,43 +30,25 @@ public class DeflateCompressionCodec extends AbstractCompressionCodec {
|
||||||
|
|
||||||
private static final String DEFLATE = "DEF";
|
private static final String DEFLATE = "DEF";
|
||||||
|
|
||||||
|
private static final StreamWrapper WRAPPER = new StreamWrapper() {
|
||||||
|
@Override
|
||||||
|
public OutputStream wrap(OutputStream out) {
|
||||||
|
return new DeflaterOutputStream(out);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getAlgorithmName() {
|
public String getAlgorithmName() {
|
||||||
return DEFLATE;
|
return DEFLATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] doCompress(byte[] payload) throws IOException {
|
protected byte[] doCompress(byte[] payload) throws IOException {
|
||||||
|
return writeAndClose(payload, WRAPPER);
|
||||||
Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION);
|
|
||||||
|
|
||||||
ByteArrayOutputStream outputStream = null;
|
|
||||||
DeflaterOutputStream deflaterOutputStream = null;
|
|
||||||
try {
|
|
||||||
outputStream = new ByteArrayOutputStream();
|
|
||||||
deflaterOutputStream = new DeflaterOutputStream(outputStream, deflater, true);
|
|
||||||
|
|
||||||
deflaterOutputStream.write(payload, 0, payload.length);
|
|
||||||
deflaterOutputStream.flush();
|
|
||||||
return outputStream.toByteArray();
|
|
||||||
} finally {
|
|
||||||
Objects.nullSafeClose(outputStream, deflaterOutputStream);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] doDecompress(byte[] compressed) throws IOException {
|
protected byte[] doDecompress(byte[] compressed) throws IOException {
|
||||||
InflaterOutputStream inflaterOutputStream = null;
|
return readAndClose(new InflaterInputStream(new ByteArrayInputStream(compressed)));
|
||||||
ByteArrayOutputStream decompressedOutputStream = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
decompressedOutputStream = new ByteArrayOutputStream();
|
|
||||||
inflaterOutputStream = new InflaterOutputStream(decompressedOutputStream);
|
|
||||||
inflaterOutputStream.write(compressed);
|
|
||||||
inflaterOutputStream.flush();
|
|
||||||
return decompressedOutputStream.toByteArray();
|
|
||||||
} finally {
|
|
||||||
Objects.nullSafeClose(decompressedOutputStream, inflaterOutputStream);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,11 +16,10 @@
|
||||||
package io.jsonwebtoken.impl.compression;
|
package io.jsonwebtoken.impl.compression;
|
||||||
|
|
||||||
import io.jsonwebtoken.CompressionCodec;
|
import io.jsonwebtoken.CompressionCodec;
|
||||||
import io.jsonwebtoken.lang.Objects;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.util.zip.GZIPInputStream;
|
import java.util.zip.GZIPInputStream;
|
||||||
import java.util.zip.GZIPOutputStream;
|
import java.util.zip.GZIPOutputStream;
|
||||||
|
|
||||||
|
@ -33,43 +32,25 @@ public class GzipCompressionCodec extends AbstractCompressionCodec implements Co
|
||||||
|
|
||||||
private static final String GZIP = "GZIP";
|
private static final String GZIP = "GZIP";
|
||||||
|
|
||||||
|
private static final StreamWrapper WRAPPER = new StreamWrapper() {
|
||||||
|
@Override
|
||||||
|
public OutputStream wrap(OutputStream out) throws IOException {
|
||||||
|
return new GZIPOutputStream(out);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getAlgorithmName() {
|
public String getAlgorithmName() {
|
||||||
return GZIP;
|
return GZIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected byte[] doDecompress(byte[] compressed) throws IOException {
|
protected byte[] doCompress(byte[] payload) throws IOException {
|
||||||
byte[] buffer = new byte[512];
|
return writeAndClose(payload, WRAPPER);
|
||||||
|
|
||||||
ByteArrayOutputStream outputStream = null;
|
|
||||||
GZIPInputStream gzipInputStream = null;
|
|
||||||
ByteArrayInputStream inputStream = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
inputStream = new ByteArrayInputStream(compressed);
|
|
||||||
gzipInputStream = new GZIPInputStream(inputStream);
|
|
||||||
outputStream = new ByteArrayOutputStream();
|
|
||||||
int read = gzipInputStream.read(buffer);
|
|
||||||
while (read != -1) {
|
|
||||||
outputStream.write(buffer, 0, read);
|
|
||||||
read = gzipInputStream.read(buffer);
|
|
||||||
}
|
|
||||||
return outputStream.toByteArray();
|
|
||||||
} finally {
|
|
||||||
Objects.nullSafeClose(inputStream, gzipInputStream, outputStream);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected byte[] doCompress(byte[] payload) throws IOException {
|
@Override
|
||||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
protected byte[] doDecompress(byte[] compressed) throws IOException {
|
||||||
GZIPOutputStream compressorOutputStream = new GZIPOutputStream(outputStream, true);
|
return readAndClose(new GZIPInputStream(new ByteArrayInputStream(compressed)));
|
||||||
try {
|
|
||||||
compressorOutputStream.write(payload, 0, payload.length);
|
|
||||||
compressorOutputStream.finish();
|
|
||||||
return outputStream.toByteArray();
|
|
||||||
} finally {
|
|
||||||
Objects.nullSafeClose(compressorOutputStream, outputStream);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue