#52: class naming and JavaDoc cleanup

This commit is contained in:
Les Hazlewood 2015-10-12 13:57:36 -07:00
parent bb471be0e9
commit 0e8ee78fc4
11 changed files with 141 additions and 69 deletions

View File

@ -16,31 +16,40 @@
package io.jsonwebtoken;
/**
* Defines how to compress and decompress byte arrays.
* Compresses and decompresses byte arrays according to a compression algorithm.
*
* @since 0.5.2
* @see io.jsonwebtoken.impl.compression.DeflateCompressionCodec
* @see io.jsonwebtoken.impl.compression.GzipCompressionCodec
* @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
* The algorithm name to use as the JWT's {@code calg} header value.
*
* @return the algorithm name to use as the JWT's {@code calg} header value.
*/
String getAlgorithmName();
/**
* Takes a byte array and returns a compressed version.
* Compresses the specified byte array according to the compression {@link #getAlgorithmName() algorithm}.
*
* @param payload bytes to compress
* @return compressed bytes
* @throws CompressionException if the specified byte array cannot be compressed according to the compression
* {@link #getAlgorithmName() algorithm}.
*/
byte[] compress(byte[] payload);
byte[] compress(byte[] payload) throws CompressionException;
/**
* Takes a compressed byte array and returns a decompressed version.
* Decompresses the specified compressed byte array according to the compression
* {@link #getAlgorithmName() algorithm}. The specified byte array must already be in compressed form
* according to the {@link #getAlgorithmName() algorithm}.
*
* @param compressed compressed bytes
* @return decompressed bytes
* @throws CompressionException if the specified byte array cannot be decompressed according to the compression
* {@link #getAlgorithmName() algorithm}.
*/
byte[] decompress(byte[] compressed);
byte[] decompress(byte[] compressed) throws CompressionException;
}

View File

@ -16,16 +16,31 @@
package io.jsonwebtoken;
/**
* Resolves "calg" header to an implementation of CompressionCodec.
* Looks for a JWT {@code calg} header, and if found, returns the corresponding {@link CompressionCodec} the parser
* can use to decompress the JWT body.
*
* <p>JJWT's default {@link JwtParser} implementation supports both the
* {@link io.jsonwebtoken.impl.compression.DeflateCompressionCodec DEFLATE}
* and {@link io.jsonwebtoken.impl.compression.GzipCompressionCodec GZIP} algorithms by default - you do not need to
* specify a {@code CompressionCodecResolver} in these cases.</p>
*
* <p>However, if you want to use a compression algorithm other than {@code DEF} or {@code GZIP}, you must implement
* your own {@link CompressionCodecResolver} and specify that when
* {@link io.jsonwebtoken.JwtBuilder#compressWith(CompressionCodec) building} and
* {@link io.jsonwebtoken.JwtParser#setCompressionCodecResolver(CompressionCodecResolver) parsing} JWTs.</p>
*
* @since 0.5.2
*/
public interface CompressionCodecResolver {
/**
* Examines the header and returns a CompressionCodec if it finds one that it recognizes.
* Looks for a JWT {@code calg} header, and if found, returns the corresponding {@link CompressionCodec} the parser
* can use to decompress the JWT body.
*
* @param header of the JWT
* @return CompressionCodec matching the "calg" header, or null if there is no "calg" header.
* @return CompressionCodec matching the {@code calg} header, or null if there is no {@code calg} header.
* @throws CompressionException if a {@code calg} header value is found and not supported.
*/
CompressionCodec resolveCompressionCodec(Header header);
CompressionCodec resolveCompressionCodec(Header header) throws CompressionException;
}

View File

@ -350,10 +350,18 @@ public interface JwtBuilder extends ClaimsMutator<JwtBuilder> {
JwtBuilder signWith(SignatureAlgorithm alg, Key key);
/**
* Compresses the JWT body using the {@link CompressionCodec} passed as argument.
* Compresses the JWT body using the specified {@link CompressionCodec}.
*
* Note: Compression is not part of the Json Web Token specification and is not expected that other libraries (including
* older versions of this one) are able to consume a compressed JWT body correctly.
* <p>If your compact JWTs are large, and you want to reduce their total size during network transmission, this
* can be useful. For example, when embedding JWTs in URLs, some browsers may not support URLs longer than a
* certain length. Using compression can help ensure the compact JWT fits within that length. However, NOTE:</p>
*
* <p><b>WARNING:</b> Compression is not defined by the JWT Specification, and it is not expected that other libraries
* (including JJWT versions < 0.5.2) are able to consume a compressed JWT body correctly. Only use this method
* if you are sure that you will consume the JWT with JJWT >= 0.5.2 or another library that you know implements
* the same behavior.</p>
*
* @see io.jsonwebtoken.impl.compression.CompressionCodecs
*
* @param codec implementation of the {@link CompressionCodec} to be used.
* @return the builder for method chaining.

View File

@ -127,10 +127,10 @@ public interface JwtParser {
/**
* Sets the signing key used to verify any discovered JWS digital signature. If the specified JWT string is not
* a JWS (no signature), this key is not used.
*
* <p>
* <p>Note that this key <em>MUST</em> be a valid key for the signature algorithm found in the JWT header
* (as the {@code alg} header parameter).</p>
*
* <p>
* <p>This method overwrites any previously set key.</p>
*
* @param key the algorithm-specific signature verification key used to validate any discovered JWS digital
@ -142,12 +142,12 @@ public interface JwtParser {
/**
* Sets the signing key used to verify any discovered JWS digital signature. If the specified JWT string is not
* a JWS (no signature), this key is not used.
*
* <p>
* <p>Note that this key <em>MUST</em> be a valid key for the signature algorithm found in the JWT header
* (as the {@code alg} header parameter).</p>
*
* <p>
* <p>This method overwrites any previously set key.</p>
*
* <p>
* <p>This is a convenience method: the string argument is first BASE64-decoded to a byte array and this resulting
* byte array is used to invoke {@link #setSigningKey(byte[])}.</p>
*
@ -160,12 +160,12 @@ public interface JwtParser {
/**
* Sets the signing key used to verify any discovered JWS digital signature. If the specified JWT string is not
* a JWS (no signature), this key is not used.
*
* <p>
* <p>Note that this key <em>MUST</em> be a valid key for the signature algorithm found in the JWT header
* (as the {@code alg} header parameter).</p>
*
* <p>
* <p>This method overwrites any previously set key.</p>
*
* <p>
* <p>This is a convenience method: the string argument is first BASE64-decoded to a byte array and this resulting
* byte array is used to invoke {@link #setSigningKey(byte[])}.</p>
*
@ -178,12 +178,12 @@ public interface JwtParser {
/**
* Sets the {@link SigningKeyResolver} used to acquire the <code>signing key</code> that should be used to verify
* a JWS's signature. If the parsed String is not a JWS (no signature), this resolver is not used.
*
* <p>
* <p>Specifying a {@code SigningKeyResolver} is necessary when the signing key is not already known before parsing
* the JWT and the JWT header or payload (plaintext body or Claims) must be inspected first to determine how to
* look up the signing key. Once returned by the resolver, the JwtParser will then verify the JWS signature with the
* returned key. For example:</p>
*
* <p>
* <pre>
* Jws&lt;Claims&gt; jws = Jwts.parser().setSigningKeyResolver(new SigningKeyResolverAdapter() {
* &#64;Override
@ -193,9 +193,9 @@ public interface JwtParser {
* }})
* .parseClaimsJws(compact);
* </pre>
*
* <p>
* <p>A {@code SigningKeyResolver} is invoked once during parsing before the signature is verified.</p>
*
* <p>
* <p>This method should only be used if a signing key is not provided by the other {@code setSigningKey*} builder
* methods.</p>
*
@ -206,10 +206,22 @@ public interface JwtParser {
JwtParser setSigningKeyResolver(SigningKeyResolver signingKeyResolver);
/**
* Sets the {@link CompressionCodecResolver} used to acquire the {@link CompressionCodec} that should be used to verify
* a decompress the JWT body. If the parsed JWT is not compressed, this resolver si not used.
* Sets the {@link CompressionCodecResolver} used to acquire the {@link CompressionCodec} that should be used to
* decompress the JWT body. If the parsed JWT is not compressed, this resolver is not used.
* <p><b>NOTE:</b> Compression is not defined by the JWT Specification, and it is not expected that other libraries
* (including JJWT versions < 0.5.2) are able to consume a compressed JWT body correctly. This method is only
* useful if the compact JWT was compressed with JJWT >= 0.5.2 or another library that you know implements
* the same behavior.</p>
* <h5>Default Support</h5>
* <p>JJWT's default {@link JwtParser} implementation supports both the
* {@link io.jsonwebtoken.impl.compression.DeflateCompressionCodec DEFLATE}
* and {@link io.jsonwebtoken.impl.compression.GzipCompressionCodec GZIP} algorithms by default - you do not need to
* specify a {@code CompressionCodecResolver} in these cases.</p>
* <p>However, if you want to use a compression algorithm other than {@code DEF} or {@code GZIP}, you must implement
* your own {@link CompressionCodecResolver} and specify that via this method and also when
* {@link io.jsonwebtoken.JwtBuilder#compressWith(CompressionCodec) building} JWTs.</p>
*
* @param compressionCodecResolver the compression codec resolver used to decompress the JWT body.
* @param compressionCodecResolver the compression codec resolver used to decompress the JWT body.
* @return the parser for method chaining.
* @since 0.5.2
*/
@ -218,7 +230,7 @@ public interface JwtParser {
/**
* Returns {@code true} if the specified JWT compact string represents a signed JWT (aka a 'JWS'), {@code false}
* otherwise.
*
* <p>
* <p>Note that if you are reasonably sure that the token is signed, it is more efficient to attempt to
* parse the token (and catching exceptions if necessary) instead of calling this method first before parsing.</p>
*
@ -231,7 +243,7 @@ public interface JwtParser {
/**
* Parses the specified compact serialized JWT string based on the builder's current configuration state and
* returns the resulting JWT or JWS instance.
*
* <p>
* <p>This method returns a JWT or JWS based on the parsed string. Because it may be cumbersome to determine if it
* is a JWT or JWS, or if the body/payload is a Claims or String with {@code instanceof} checks, the
* {@link #parse(String, JwtHandler) parse(String,JwtHandler)} method allows for a type-safe callback approach that
@ -258,11 +270,11 @@ public interface JwtParser {
/**
* Parses the specified compact serialized JWT string based on the builder's current configuration state and
* invokes the specified {@code handler} with the resulting JWT or JWS instance.
*
* <p>
* <p>If you are confident of the format of the JWT before parsing, you can create an anonymous subclass using the
* {@link io.jsonwebtoken.JwtHandlerAdapter JwtHandlerAdapter} and override only the methods you know are relevant
* for your use case(s), for example:</p>
*
* <p>
* <pre>
* String compactJwt = request.getParameter("jwt"); //we are confident this is a signed JWS
*
@ -273,10 +285,10 @@ public interface JwtParser {
* }
* });
* </pre>
*
* <p>
* <p>If you know the JWT string can be only one type of JWT, then it is even easier to invoke one of the
* following convenience methods instead of this one:</p>
*
* <p>
* <ul>
* <li>{@link #parsePlaintextJwt(String)}</li>
* <li>{@link #parseClaimsJwt(String)}</li>
@ -302,17 +314,17 @@ public interface JwtParser {
* @since 0.2
*/
<T> T parse(String jwt, JwtHandler<T> handler)
throws ExpiredJwtException, UnsupportedJwtException, MalformedJwtException, SignatureException, IllegalArgumentException;
throws ExpiredJwtException, UnsupportedJwtException, MalformedJwtException, SignatureException, IllegalArgumentException;
/**
* Parses the specified compact serialized JWT string based on the builder's current configuration state and
* returns
* the resulting unsigned plaintext JWT instance.
*
* <p>
* <p>This is a convenience method that is usable if you are confident that the compact string argument reflects an
* unsigned plaintext JWT. An unsigned plaintext JWT has a String (non-JSON) body payload and it is not
* cryptographically signed.</p>
*
* <p>
* <p><b>If the compact string presented does not reflect an unsigned plaintext JWT with non-JSON string body,
* an {@link UnsupportedJwtException} will be thrown.</b></p>
*
@ -332,17 +344,17 @@ public interface JwtParser {
* @since 0.2
*/
Jwt<Header, String> parsePlaintextJwt(String plaintextJwt)
throws UnsupportedJwtException, MalformedJwtException, SignatureException, IllegalArgumentException;
throws UnsupportedJwtException, MalformedJwtException, SignatureException, IllegalArgumentException;
/**
* Parses the specified compact serialized JWT string based on the builder's current configuration state and
* returns
* the resulting unsigned plaintext JWT instance.
*
* <p>
* <p>This is a convenience method that is usable if you are confident that the compact string argument reflects an
* unsigned Claims JWT. An unsigned Claims JWT has a {@link Claims} body and it is not cryptographically
* signed.</p>
*
* <p>
* <p><b>If the compact string presented does not reflect an unsigned Claims JWT, an
* {@link UnsupportedJwtException} will be thrown.</b></p>
*
@ -363,17 +375,17 @@ public interface JwtParser {
* @since 0.2
*/
Jwt<Header, Claims> parseClaimsJwt(String claimsJwt)
throws ExpiredJwtException, UnsupportedJwtException, MalformedJwtException, SignatureException, IllegalArgumentException;
throws ExpiredJwtException, UnsupportedJwtException, MalformedJwtException, SignatureException, IllegalArgumentException;
/**
* Parses the specified compact serialized JWS string based on the builder's current configuration state and
* returns
* the resulting plaintext JWS instance.
*
* <p>
* <p>This is a convenience method that is usable if you are confident that the compact string argument reflects a
* plaintext JWS. A plaintext JWS is a JWT with a String (non-JSON) body (payload) that has been
* cryptographically signed.</p>
*
* <p>
* <p><b>If the compact string presented does not reflect a plaintext JWS, an {@link UnsupportedJwtException}
* will be thrown.</b></p>
*
@ -391,16 +403,16 @@ public interface JwtParser {
* @since 0.2
*/
Jws<String> parsePlaintextJws(String plaintextJws)
throws UnsupportedJwtException, MalformedJwtException, SignatureException, IllegalArgumentException;
throws UnsupportedJwtException, MalformedJwtException, SignatureException, IllegalArgumentException;
/**
* Parses the specified compact serialized JWS string based on the builder's current configuration state and
* returns
* the resulting Claims JWS instance.
*
* <p>
* <p>This is a convenience method that is usable if you are confident that the compact string argument reflects a
* Claims JWS. A Claims JWS is a JWT with a {@link Claims} body that has been cryptographically signed.</p>
*
* <p>
* <p><b>If the compact string presented does not reflect a Claims JWS, an {@link UnsupportedJwtException} will be
* thrown.</b></p>
*
@ -420,5 +432,5 @@ public interface JwtParser {
* @since 0.2
*/
Jws<Claims> parseClaimsJws(String claimsJws)
throws ExpiredJwtException, UnsupportedJwtException, MalformedJwtException, SignatureException, IllegalArgumentException;
throws ExpiredJwtException, UnsupportedJwtException, MalformedJwtException, SignatureException, IllegalArgumentException;
}

View File

@ -26,13 +26,12 @@ import io.jsonwebtoken.IncorrectClaimException;
import io.jsonwebtoken.InvalidClaimException;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.JwsHeader;
import io.jsonwebtoken.MissingClaimException;
import io.jsonwebtoken.SigningKeyResolver;
import io.jsonwebtoken.Jwt;
import io.jsonwebtoken.JwtHandler;
import io.jsonwebtoken.JwtHandlerAdapter;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.MissingClaimException;
import io.jsonwebtoken.PrematureJwtException;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.SignatureException;

View File

@ -22,13 +22,15 @@ import io.jsonwebtoken.lang.Assert;
import java.io.IOException;
/**
* Base class that asserts arguments and wraps IOException with CompressionException.
* Abstract class that asserts arguments and wraps IOException with CompressionException.
*
* @since 0.5.2
*/
public abstract class BaseCompressionCodec implements CompressionCodec {
public abstract class AbstractCompressionCodec 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
@ -36,10 +38,11 @@ public abstract class BaseCompressionCodec implements CompressionCodec {
protected abstract byte[] doCompress(byte[] payload) throws IOException;
/**
* Asserts that payload is not null and calls doCompress
* Asserts that payload is not null and calls {@link #doCompress(byte[]) doCompress}
*
* @param payload bytes to compress
* @return compressed bytes
* @throws CompressionException if doCompress throws an IOException
* @throws CompressionException if {@link #doCompress(byte[]) doCompress} throws an IOException
*/
@Override
public final byte[] compress(byte[] payload) {
@ -53,10 +56,11 @@ public abstract class BaseCompressionCodec implements CompressionCodec {
}
/**
* Asserts the compressed bytes is not null and calls doDecompress
* Asserts the compressed bytes is not null and calls {@link #doDecompress(byte[]) doDecompress}
*
* @param compressed compressed bytes
* @return decompressed bytes
* @throws CompressionException if doCompress throws an IOException
* @throws CompressionException if {@link #doDecompress(byte[]) doDecompress} throws an IOException
*/
@Override
public final byte[] decompress(byte[] compressed) {
@ -71,6 +75,7 @@ public abstract class BaseCompressionCodec implements CompressionCodec {
/**
* 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

View File

@ -18,20 +18,27 @@ package io.jsonwebtoken.impl.compression;
import io.jsonwebtoken.CompressionCodec;
/**
* CompressionCodecs exposes default implementation of the {@link CompressionCodec} interface.
* Provides default implementations of the {@link CompressionCodec} interface.
*
* @see #DEFLATE
* @see #GZIP
*
* @since 0.5.2
*/
public interface CompressionCodecs {
public final class CompressionCodecs {
private static final CompressionCodecs I = new CompressionCodecs();
private CompressionCodecs(){} //prevent external instantiation
/**
* Codec implementing the <a href="https://en.wikipedia.org/wiki/DEFLATE">deflate</a> compression algorithm
*/
CompressionCodec DEFLATE = new DeflateCompressionCodec();
public static final CompressionCodec DEFLATE = new DeflateCompressionCodec();
/**
* Codec implementing the <a href="https://en.wikipedia.org/wiki/Gzip">gzip</a> compression algorithm
*/
CompressionCodec GZIP = new GzipCompressionCodec();
public static final CompressionCodec GZIP = new GzipCompressionCodec();
}

View File

@ -23,9 +23,24 @@ import io.jsonwebtoken.lang.Assert;
import io.jsonwebtoken.lang.Strings;
/**
* Default implementation of {@link CompressionCodecResolver}. This implementation will resolve DEF to
* {@link DeflateCompressionCodec} and GZIP to {@link GzipCompressionCodec}.
* Default implementation of {@link CompressionCodecResolver} that supports the following:
* <p>
* <ul>
* <li>If the specified JWT {@link Header} does not have a {@code calg} header, this implementation does
* nothing and returns {@code null} to the caller, indicating no compression was used.</li>
* <li>If the header has a {@code calg} value of {@code DEF}, a {@link DeflateCompressionCodec} will be returned.</li>
* <li>If the header has a {@code calg} value of {@code GZIP}, a {@link GzipCompressionCodec} will be returned.</li>
* <li>If the header has any other {@code calg} value, a {@link CompressionException} is thrown to reflect an
* unrecognized algorithm.</li>
* </ul>
*
* <p>If you want to use a compression algorithm other than {@code DEF} or {@code GZIP}, you must implement your own
* {@link CompressionCodecResolver} and specify that when
* {@link io.jsonwebtoken.JwtBuilder#compressWith(CompressionCodec) building} and
* {@link io.jsonwebtoken.JwtParser#setCompressionCodecResolver(CompressionCodecResolver) parsing} JWTs.</p>
*
* @see DeflateCompressionCodec
* @see GzipCompressionCodec
* @since 0.5.2
*/
public class DefaultCompressionCodecResolver implements CompressionCodecResolver {
@ -35,6 +50,7 @@ public class DefaultCompressionCodecResolver implements CompressionCodecResolver
String cmpAlg = getAlgorithmFromHeader(header);
final boolean hasCompressionAlgorithm = Strings.hasText(cmpAlg);
if (!hasCompressionAlgorithm) {
return null;
}

View File

@ -24,10 +24,11 @@ import java.util.zip.DeflaterOutputStream;
import java.util.zip.InflaterOutputStream;
/**
* Codec implementing the <a href="https://en.wikipedia.org/wiki/DEFLATE">deflate</a> compression algorithm
* Codec implementing the <a href="https://en.wikipedia.org/wiki/DEFLATE">deflate compression algorithm</a>.
*
* @since 0.5.2
*/
public class DeflateCompressionCodec extends BaseCompressionCodec {
public class DeflateCompressionCodec extends AbstractCompressionCodec {
private static final String DEFLATE = "DEF";

View File

@ -25,11 +25,11 @@ import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
/**
* Codec implementing the <a href="https://en.wikipedia.org/wiki/Gzip">gzip</a> compression algorithm
* Codec implementing the <a href="https://en.wikipedia.org/wiki/Gzip">gzip compression algorithm</a>.
*
* @since 0.5.2
*/
public class GzipCompressionCodec extends BaseCompressionCodec implements CompressionCodec {
public class GzipCompressionCodec extends AbstractCompressionCodec implements CompressionCodec {
private static final String GZIP = "GZIP";

View File

@ -22,8 +22,8 @@ import org.junit.Test
/**
* @since 0.5.2
*/
class BaseCompressionCodecTest {
static class ExceptionThrowingCodec extends BaseCompressionCodec {
class AbstractCompressionCodecTest {
static class ExceptionThrowingCodec extends AbstractCompressionCodec {
@Override
protected byte[] doCompress(byte[] payload) throws IOException {