Skip to content

Commit

Permalink
Merge branch 'Issue-52' of github.com:josebarrueta/jjwt into Issue-52
Browse files Browse the repository at this point in the history
  • Loading branch information
josebarrueta committed Sep 24, 2015
2 parents 257bddc + 20e80ff commit 269a143
Show file tree
Hide file tree
Showing 9 changed files with 275 additions and 61 deletions.
18 changes: 16 additions & 2 deletions src/main/java/io/jsonwebtoken/CompressionCodec.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,29 @@
package io.jsonwebtoken;

/**
* CompressionCodec
* Defines how to compress and decompress byte arrays.
*
* @since 0.59
* @since 0.5.2
*/
public interface CompressionCodec {

/**
* The algorithm name that would appear in the JWT header.
* @return the algorithm name that would appear in the JWT header
*/
String getAlgorithmName();

/**
* Takes a byte array and returns a compressed version.
* @param payload bytes to compress
* @return compressed bytes
*/
byte[] compress(byte[] payload);

/**
* Takes a compressed byte array and returns a decompressed version.
* @param compressed compressed bytes
* @return decompressed bytes
*/
byte[] decompress(byte[] compressed);
}
8 changes: 6 additions & 2 deletions src/main/java/io/jsonwebtoken/CompressionCodecResolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,16 @@
package io.jsonwebtoken;

/**
* CompressionCodecResolver
* Resolves "calg" header to an implementation of CompressionCodec.
*
* @since 0.5.2
*/
public interface CompressionCodecResolver {

/**
* Examines the header and returns a CompressionCodec if it finds one that it recognizes.
* @param header of the JWT
* @return CompressionCodec matching the "calg" header, or null if there is no "calg" header.
*/
CompressionCodec resolveCompressionCodec(Header header);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright (C) 2015 jsonwebtoken.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.jsonwebtoken.impl.compression;

import io.jsonwebtoken.CompressionCodec;
import io.jsonwebtoken.CompressionException;
import io.jsonwebtoken.lang.Assert;

import java.io.IOException;

/**
* Base class that asserts arguments and wraps IOException with CompressionException.
*
* @since 0.5.2
*/
public abstract class BaseCompressionCodec implements CompressionCodec {
/**
* Implement this method to do the actual work of compressing the payload
* @param payload the bytes to compress
* @return the compressed bytes
* @throws IOException if the compression causes an IOException
*/
protected abstract byte[] doCompress(byte[] payload) throws IOException;

/**
* Asserts that payload is not null and calls doCompress
* @param payload bytes to compress
* @return compressed bytes
* @throws CompressionException if doCompress throws an IOException
*/
@Override
public final byte[] compress(byte[] payload) {
Assert.notNull(payload, "payload cannot be null.");

try {
return doCompress(payload);
} catch (IOException e) {
throw new CompressionException("Unable to compress payload.", e);
}
}

/**
* Asserts the compressed bytes is not null and calls doDecompress
* @param compressed compressed bytes
* @return decompressed bytes
* @throws CompressionException if doCompress throws an IOException
*/
@Override
public final byte[] decompress(byte[] compressed) {
Assert.notNull(compressed, "compressed bytes cannot be null.");

try {
return doDecompress(compressed);
} catch (IOException e) {
throw new CompressionException("Unable to decompress bytes.", e);
}
}

/**
* Implement this method to do the actual work of decompressing the compressed bytes.
* @param compressed compressed bytes
* @return decompressed bytes
* @throws IOException if the decompression runs into an IO problem
*/
protected abstract byte[] doDecompress(byte[] compressed) throws IOException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,16 @@
*
* @since 0.5.2
*/
public abstract class CompressionCodecs {
public interface CompressionCodecs {

private CompressionCodecs(){}

public static final CompressionCodec DEFLATE = new DeflateCompressionCodec();

public static final CompressionCodec GZIP = new GzipCompressionCodec();
/**
* Codec implementing the <a href="https://en.wikipedia.org/wiki/DEFLATE">deflate</a> compression algorithm
*/
CompressionCodec DEFLATE = new DeflateCompressionCodec();

/**
* Codec implementing the <a href="https://en.wikipedia.org/wiki/Gzip">gzip</a> compression algorithm
*/
CompressionCodec GZIP = new GzipCompressionCodec();

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,30 +23,34 @@
import io.jsonwebtoken.lang.Strings;

/**
* DefaultCompressionCodecResolver
* Default implementation of {@link CompressionCodecResolver}. This implementation will resolve DEF to
* {@link DeflateCompressionCodec} and GZIP to {@link GzipCompressionCodec}.
*
* @since 0.5.2
*/
public class DefaultCompressionCodecResolver implements CompressionCodecResolver {

@Override
public CompressionCodec resolveCompressionCodec(Header header) {
Assert.notNull(header, "header cannot be null.");

String cmpAlg = header.getCompressionAlgorithm();
String cmpAlg = getAlgorithmFromHeader(header);

if (!Strings.hasText(cmpAlg)) {
final boolean hasCompressionAlgorithm = Strings.hasText(cmpAlg);
if (!hasCompressionAlgorithm) {
return null;
}

if (CompressionCodecs.DEFLATE.getAlgorithmName().equalsIgnoreCase(cmpAlg)) {
return CompressionCodecs.DEFLATE;
}

if (CompressionCodecs.GZIP.getAlgorithmName().equalsIgnoreCase(cmpAlg)) {
return CompressionCodecs.GZIP;
}

throw new CompressionException("Unsupported compression algorithm '" + cmpAlg + "'");
}

private String getAlgorithmFromHeader(Header header) {
Assert.notNull(header, "header cannot be null.");

return header.getCompressionAlgorithm();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@
*/
package io.jsonwebtoken.impl.compression;

import io.jsonwebtoken.CompressionCodec;
import io.jsonwebtoken.CompressionException;
import io.jsonwebtoken.lang.Assert;
import io.jsonwebtoken.lang.Objects;

import java.io.ByteArrayOutputStream;
Expand All @@ -27,11 +24,10 @@
import java.util.zip.InflaterOutputStream;

/**
* DeflateCompressionCodec
*
* Codec implementing the <a href="https://en.wikipedia.org/wiki/DEFLATE">deflate</a> compression algorithm
* @since 0.5.2
*/
public class DeflateCompressionCodec implements CompressionCodec {
public class DeflateCompressionCodec extends BaseCompressionCodec {

private static final String DEFLATE = "DEF";

Expand All @@ -41,8 +37,7 @@ public String getAlgorithmName() {
}

@Override
public byte[] compress(byte[] payload) {
Assert.notNull(payload, "payload cannot be null.");
public byte[] doCompress(byte[] payload) throws IOException {

Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION);

Expand All @@ -55,17 +50,13 @@ public byte[] compress(byte[] payload) {
deflaterOutputStream.write(payload, 0, payload.length);
deflaterOutputStream.flush();
return outputStream.toByteArray();
} catch (IOException e) {
throw new CompressionException("Unable to compress payload.", e);
} finally {
Objects.nullSafeClose(outputStream, deflaterOutputStream);
}
}

@Override
public byte[] decompress(byte[] compressed) {
Assert.notNull(compressed, "compressed cannot be null.");

public byte[] doDecompress(byte[] compressed) throws IOException {
InflaterOutputStream inflaterOutputStream = null;
ByteArrayOutputStream decompressedOutputStream = null;

Expand All @@ -75,8 +66,6 @@ public byte[] decompress(byte[] compressed) {
inflaterOutputStream.write(compressed);
inflaterOutputStream.flush();
return decompressedOutputStream.toByteArray();
} catch (IOException e) {
throw new CompressionException("Unable to decompress compressed payload.", e);
} finally {
Objects.nullSafeClose(decompressedOutputStream, inflaterOutputStream);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
package io.jsonwebtoken.impl.compression;

import io.jsonwebtoken.CompressionCodec;
import io.jsonwebtoken.CompressionException;
import io.jsonwebtoken.lang.Assert;
import io.jsonwebtoken.lang.Objects;

import java.io.ByteArrayInputStream;
Expand All @@ -27,11 +25,11 @@
import java.util.zip.GZIPOutputStream;

/**
* GzipCompressionCodec
* Codec implementing the <a href="https://en.wikipedia.org/wiki/Gzip">gzip</a> compression algorithm
*
* @since 0.5.2
*/
public class GzipCompressionCodec implements CompressionCodec {
public class GzipCompressionCodec extends BaseCompressionCodec implements CompressionCodec {

private static final String GZIP = "GZIP";

Expand All @@ -41,29 +39,7 @@ public String getAlgorithmName() {
}

@Override
public byte[] compress(byte[] payload) {
Assert.notNull(payload, "payload cannot be null.");

ByteArrayOutputStream outputStream = null;
GZIPOutputStream gzipOutputStream = null;

try {
outputStream = new ByteArrayOutputStream();
gzipOutputStream = new GZIPOutputStream(outputStream, true);
gzipOutputStream.write(payload, 0, payload.length);
gzipOutputStream.finish();
return outputStream.toByteArray();
} catch (IOException e) {
throw new CompressionException("Unable to compress payload.", e);
} finally {
Objects.nullSafeClose(outputStream, gzipOutputStream);
}
}

@Override
public byte[] decompress(byte[] compressed) {
Assert.notNull(compressed, "compressed cannot be null.");

protected byte[] doDecompress(byte[] compressed) throws IOException {
byte[] buffer = new byte[512];

ByteArrayOutputStream outputStream = null;
Expand All @@ -79,10 +55,20 @@ public byte[] decompress(byte[] compressed) {
outputStream.write(buffer, 0, read);
}
return outputStream.toByteArray();
} catch (IOException e) {
throw new CompressionException("Unable to decompress compressed payload.", e);
} finally {
Objects.nullSafeClose(inputStream, gzipInputStream, outputStream);
}
}

protected byte[] doCompress(byte[] payload) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
GZIPOutputStream compressorOutputStream = new GZIPOutputStream(outputStream, true);
try {
compressorOutputStream.write(payload, 0, payload.length);
compressorOutputStream.finish();
return outputStream.toByteArray();
} finally {
Objects.nullSafeClose(compressorOutputStream, outputStream);
}
}
}
Loading

0 comments on commit 269a143

Please sign in to comment.