348: Reorganize into a multi-module project. Includes test enhancements and code reorganization

This commit is contained in:
Les Hazlewood 2018-07-12 11:44:14 -04:00
parent 29172608a9
commit 439c027c2e
190 changed files with 1637 additions and 678 deletions

View File

@ -1,7 +1,6 @@
# https://travis-ci.org/jwtk/jjwt
dist: trusty
sudo: required
#sudo: required
language: java
jdk:
- openjdk7
@ -9,16 +8,15 @@ jdk:
- oraclejdk9
- oraclejdk10
- openjdk10
- oraclejdk-ea
- openjdk11
# - openjdk11
# - oraclejdk-ea
before_install:
- export BUILD_COVERAGE="$([ $TRAVIS_JDK_VERSION == 'oraclejdk8' ] && echo 'true')"
install: echo "No need to run mvn install -DskipTests then mvn install. Running mvn install."
install: true
script: mvn install
after_success:
- test -z "$BUILD_COVERAGE" || mvn clean test clover:check clover:clover coveralls:report
- test -z "$BUILD_COVERAGE" || { mvn clean clover:setup test && mvn -pl . clover:clover clover:check coveralls:report; }

2
NOTICE
View File

@ -1,4 +1,4 @@
The io.jsonwebtoken.codec.impl.Base64 implementation is based on MigBase64 with modifications for Base64 URL support. This
The Base64 implementation is based on MigBase64 with modifications for Base64 URL support. This
class's copyright and license notice have been retained and are repeated here per that code's requirements:
**** BEGIN MIGBASE64 NOTICE *****

View File

@ -89,7 +89,7 @@ Most complexity is hidden behind a convenient and readable builder-based [fluent
```java
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.impl.crypto.MacProvider;
import MacProvider; //TODO: clean up via https://github.com/jwtk/jjwt/issues/350
import java.security.Key;
// We need a signing key, so we'll create one just for this example. Usually
@ -154,7 +154,7 @@ You can use the following rules on your Android projects (see [Proguard Exclusio
-keepnames interface io.jsonwebtoken.* { *; }
-dontwarn javax.xml.bind.DatatypeConverter
-dontwarn io.jsonwebtoken.impl.Base64Codec
-dontwarn Base64Codec
-keepnames class com.fasterxml.jackson.** { *; }
-keepnames interface com.fasterxml.jackson.** { *; }

36
api/pom.xml Normal file
View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2018 JWTK
~
~ 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-root</artifactId>
<version>0.10.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>jjwt-api</artifactId>
<name>JJWT :: API</name>
<packaging>jar</packaging>
<properties>
<jjwt.root>${basedir}/..</jjwt.root>
</properties>
</project>

View File

@ -18,16 +18,16 @@ package io.jsonwebtoken;
/**
* Compresses and decompresses byte arrays according to a compression algorithm.
*
* @see io.jsonwebtoken.impl.compression.DeflateCompressionCodec
* @see io.jsonwebtoken.impl.compression.GzipCompressionCodec
* @see CompressionCodecs#DEFLATE
* @see CompressionCodecs#GZIP
* @since 0.6.0
*/
public interface CompressionCodec {
/**
* The algorithm name to use as the JWT's {@code zip} header value.
* The compression algorithm name to use as the JWT's {@code zip} header value.
*
* @return the algorithm name to use as the JWT's {@code zip} header value.
* @return the compression algorithm name to use as the JWT's {@code zip} header value.
*/
String getAlgorithmName();

View File

@ -20,8 +20,8 @@ package io.jsonwebtoken;
* 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
* {@link CompressionCodecs#DEFLATE DEFLATE}
* and {@link CompressionCodecs#GZIP 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

View File

@ -1,7 +1,6 @@
package io.jsonwebtoken;
import io.jsonwebtoken.impl.compression.DeflateCompressionCodec;
import io.jsonwebtoken.impl.compression.GzipCompressionCodec;
import io.jsonwebtoken.lang.Classes;
/**
* Provides default implementations of the {@link CompressionCodec} interface.
@ -12,15 +11,15 @@ import io.jsonwebtoken.impl.compression.GzipCompressionCodec;
*/
public final class CompressionCodecs {
private static final CompressionCodecs INSTANCE = new CompressionCodecs();
private CompressionCodecs() {} //prevent external instantiation
private CompressionCodecs() {
} //prevent external instantiation
/**
* Codec implementing the <a href="https://tools.ietf.org/html/rfc7518">JWA</a> standard
* <a href="https://en.wikipedia.org/wiki/DEFLATE">deflate</a> compression algorithm
*/
public static final CompressionCodec DEFLATE = new DeflateCompressionCodec();
public static final CompressionCodec DEFLATE =
Classes.newInstance("io.jsonwebtoken.impl.compression.DeflateCompressionCodec");
/**
* Codec implementing the <a href="https://en.wikipedia.org/wiki/Gzip">gzip</a> compression algorithm.
@ -29,6 +28,7 @@ public final class CompressionCodecs {
* that all parties accessing the token support the gzip algorithm.</p>
* <p>If you're concerned about compatibility, the {@link #DEFLATE DEFLATE} code is JWA standards-compliant.</p>
*/
public static final CompressionCodec GZIP = new GzipCompressionCodec();
public static final CompressionCodec GZIP =
Classes.newInstance("io.jsonwebtoken.impl.compression.GzipCompressionCodec");
}

View File

@ -22,6 +22,7 @@ package io.jsonwebtoken;
* @since 0.6
*/
public class IncorrectClaimException extends InvalidClaimException {
public IncorrectClaimException(Header header, Claims claims, String message) {
super(header, claims, message);
}

View File

@ -25,6 +25,7 @@ package io.jsonwebtoken;
* @since 0.6
*/
public class InvalidClaimException extends ClaimJwtException {
private String claimName;
private Object claimValue;

View File

@ -15,7 +15,7 @@
*/
package io.jsonwebtoken;
import io.jsonwebtoken.codec.Encoder;
import io.jsonwebtoken.io.Encoder;
import io.jsonwebtoken.io.Serializer;
import java.security.Key;

View File

@ -15,8 +15,7 @@
*/
package io.jsonwebtoken;
import io.jsonwebtoken.codec.Decoder;
import io.jsonwebtoken.impl.DefaultClock;
import io.jsonwebtoken.io.Decoder;
import io.jsonwebtoken.io.Deserializer;
import java.security.Key;
@ -131,7 +130,7 @@ public interface JwtParser {
/**
* Sets the {@link Clock} that determines the timestamp to use when validating the parsed JWT.
* The parser uses a {@link DefaultClock DefaultClock} instance by default.
* The parser uses a default Clock implementation that simply returns {@code new Date()} when called.
*
* @param clock a {@code Clock} object to return the timestamp to use when validating the parsed JWT.
* @return the parser for method chaining.
@ -259,8 +258,8 @@ public interface JwtParser {
* the same behavior.</p>
* <h3>Default Support</h3>
* <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
* {@link CompressionCodecs#DEFLATE DEFLATE}
* and {@link CompressionCodecs#GZIP 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

View File

@ -15,11 +15,7 @@
*/
package io.jsonwebtoken;
import io.jsonwebtoken.impl.DefaultClaims;
import io.jsonwebtoken.impl.DefaultHeader;
import io.jsonwebtoken.impl.DefaultJwsHeader;
import io.jsonwebtoken.impl.DefaultJwtBuilder;
import io.jsonwebtoken.impl.DefaultJwtParser;
import io.jsonwebtoken.lang.Classes;
import java.util.Map;
@ -31,7 +27,10 @@ import java.util.Map;
*/
public final class Jwts {
private Jwts(){}
private static final Class[] MAP_ARG = new Class[]{Map.class};
private Jwts() {
}
/**
* Creates a new {@link Header} instance suitable for <em>plaintext</em> (not digitally signed) JWTs. As this
@ -41,7 +40,7 @@ public final class Jwts {
* @return a new {@link Header} instance suitable for <em>plaintext</em> (not digitally signed) JWTs.
*/
public static Header header() {
return new DefaultHeader();
return Classes.newInstance("io.jsonwebtoken.impl.DefaultHeader");
}
/**
@ -52,7 +51,7 @@ public final class Jwts {
* @return a new {@link Header} instance suitable for <em>plaintext</em> (not digitally signed) JWTs.
*/
public static Header header(Map<String, Object> header) {
return new DefaultHeader(header);
return Classes.newInstance("io.jsonwebtoken.impl.DefaultHeader", MAP_ARG, header);
}
/**
@ -62,7 +61,7 @@ public final class Jwts {
* @see JwtBuilder#setHeader(Header)
*/
public static JwsHeader jwsHeader() {
return new DefaultJwsHeader();
return Classes.newInstance("io.jsonwebtoken.impl.DefaultJwsHeader");
}
/**
@ -74,7 +73,7 @@ public final class Jwts {
* @see JwtBuilder#setHeader(Header)
*/
public static JwsHeader jwsHeader(Map<String, Object> header) {
return new DefaultJwsHeader(header);
return Classes.newInstance("io.jsonwebtoken.impl.DefaultJwsHeader", MAP_ARG, header);
}
/**
@ -83,7 +82,7 @@ public final class Jwts {
* @return a new {@link Claims} instance to be used as a JWT body.
*/
public static Claims claims() {
return new DefaultClaims();
return Classes.newInstance("io.jsonwebtoken.impl.DefaultClaims");
}
/**
@ -93,7 +92,7 @@ public final class Jwts {
* @return a new {@link Claims} instance populated with the specified name/value pairs.
*/
public static Claims claims(Map<String, Object> claims) {
return new DefaultClaims(claims);
return Classes.newInstance("io.jsonwebtoken.impl.DefaultClaims", MAP_ARG, claims);
}
/**
@ -102,7 +101,7 @@ public final class Jwts {
* @return a new {@link JwtParser} instance that can be configured and then used to parse JWT strings.
*/
public static JwtParser parser() {
return new DefaultJwtParser();
return Classes.newInstance("io.jsonwebtoken.impl.DefaultJwtParser");
}
/**
@ -113,6 +112,6 @@ public final class Jwts {
* strings.
*/
public static JwtBuilder builder() {
return new DefaultJwtBuilder();
return Classes.newInstance("io.jsonwebtoken.impl.DefaultJwtBuilder");
}
}

View File

@ -1,4 +1,4 @@
package io.jsonwebtoken.codec.impl;
package io.jsonwebtoken.io;
import java.util.Arrays;
@ -18,6 +18,7 @@ import java.util.Arrays;
*
* @author Mikael Grev
* @author Les Hazlewood
* @since 0.10.0
*/
@SuppressWarnings("Duplicates")
final class Base64 { //final and package-protected on purpose

View File

@ -1,12 +1,13 @@
package io.jsonwebtoken.codec.impl;
package io.jsonwebtoken.io;
import io.jsonwebtoken.codec.Decoder;
import io.jsonwebtoken.codec.DecodingException;
import io.jsonwebtoken.lang.Assert;
public class Base64Decoder extends Base64Support implements Decoder<String, byte[]> {
/**
* @since 0.10.0
*/
class Base64Decoder extends Base64Support implements Decoder<String, byte[]> {
public Base64Decoder() {
Base64Decoder() {
super(Base64.DEFAULT);
}

View File

@ -1,12 +1,13 @@
package io.jsonwebtoken.codec.impl;
package io.jsonwebtoken.io;
import io.jsonwebtoken.codec.Encoder;
import io.jsonwebtoken.codec.EncodingException;
import io.jsonwebtoken.lang.Assert;
public class Base64Encoder extends Base64Support implements Encoder<byte[], String> {
/**
* @since 0.10.0
*/
class Base64Encoder extends Base64Support implements Encoder<byte[], String> {
public Base64Encoder() {
Base64Encoder() {
super(Base64.DEFAULT);
}

View File

@ -1,8 +1,11 @@
package io.jsonwebtoken.codec.impl;
package io.jsonwebtoken.io;
import io.jsonwebtoken.lang.Assert;
public class Base64Support {
/**
* @since 0.10.0
*/
class Base64Support {
protected final Base64 base64;

View File

@ -0,0 +1,11 @@
package io.jsonwebtoken.io;
/**
* @since 0.10.0
*/
class Base64UrlDecoder extends Base64Decoder {
Base64UrlDecoder() {
super(Base64.URL_SAFE);
}
}

View File

@ -0,0 +1,11 @@
package io.jsonwebtoken.io;
/**
* @since 0.10.0
*/
class Base64UrlEncoder extends Base64Encoder {
Base64UrlEncoder() {
super(Base64.URL_SAFE);
}
}

View File

@ -1,11 +1,9 @@
package io.jsonwebtoken.codec;
import io.jsonwebtoken.JwtException;
package io.jsonwebtoken.io;
/**
* @since 0.10.0
*/
public class CodecException extends JwtException {
public class CodecException extends IOException {
public CodecException(String message, Throwable cause) {
super(message, cause);

View File

@ -0,0 +1,9 @@
package io.jsonwebtoken.io;
/**
* @since 0.10.0
*/
public interface Decoder<T, R> {
R decode(T t) throws DecodingException;
}

View File

@ -0,0 +1,13 @@
package io.jsonwebtoken.io;
/**
* @since 0.10.0
*/
public final class Decoders {
public static final Decoder<String, byte[]> BASE64 = new ExceptionPropagatingDecoder<>(new Base64Decoder());
public static final Decoder<String, byte[]> BASE64URL = new ExceptionPropagatingDecoder<>(new Base64UrlDecoder());
private Decoders() { //prevent instantiation
}
}

View File

@ -1,4 +1,4 @@
package io.jsonwebtoken.codec;
package io.jsonwebtoken.io;
/**
* @since 0.10.0

View File

@ -1,5 +1,8 @@
package io.jsonwebtoken.io;
/**
* @since 0.10.0
*/
public class DeserializationException extends SerialException {
public DeserializationException(String msg) {

View File

@ -1,5 +1,8 @@
package io.jsonwebtoken.io;
/**
* @since 0.10.0
*/
public interface Deserializer<T> {
T deserialize(byte[] bytes) throws DeserializationException;

View File

@ -0,0 +1,9 @@
package io.jsonwebtoken.io;
/**
* @since 0.10.0
*/
public interface Encoder<T, R> {
R encode(T t) throws EncodingException;
}

View File

@ -0,0 +1,13 @@
package io.jsonwebtoken.io;
/**
* @since 0.10.0
*/
public final class Encoders {
public static final Encoder<byte[], String> BASE64 = new ExceptionPropagatingEncoder<>(new Base64Encoder());
public static final Encoder<byte[], String> BASE64URL = new ExceptionPropagatingEncoder<>(new Base64UrlEncoder());
private Encoders() { //prevent instantiation
}
}

View File

@ -1,4 +1,4 @@
package io.jsonwebtoken.codec;
package io.jsonwebtoken.io;
/**
* @since 0.10.0

View File

@ -1,14 +1,15 @@
package io.jsonwebtoken.codec.impl;
package io.jsonwebtoken.io;
import io.jsonwebtoken.codec.Decoder;
import io.jsonwebtoken.codec.DecodingException;
import io.jsonwebtoken.lang.Assert;
public class ExceptionPropagatingDecoder<T, R> implements Decoder<T, R> {
/**
* @since 0.10.0
*/
class ExceptionPropagatingDecoder<T, R> implements Decoder<T, R> {
private final Decoder<T, R> decoder;
public ExceptionPropagatingDecoder(Decoder<T, R> decoder) {
ExceptionPropagatingDecoder(Decoder<T, R> decoder) {
Assert.notNull(decoder, "Decoder cannot be null.");
this.decoder = decoder;
}

View File

@ -1,14 +1,15 @@
package io.jsonwebtoken.codec.impl;
package io.jsonwebtoken.io;
import io.jsonwebtoken.codec.Encoder;
import io.jsonwebtoken.codec.EncodingException;
import io.jsonwebtoken.lang.Assert;
public class ExceptionPropagatingEncoder<T,R> implements Encoder<T,R> {
/**
* @since 0.10.0
*/
class ExceptionPropagatingEncoder<T, R> implements Encoder<T, R> {
private final Encoder<T,R> encoder;
private final Encoder<T, R> encoder;
public ExceptionPropagatingEncoder(Encoder<T,R> encoder) {
ExceptionPropagatingEncoder(Encoder<T, R> encoder) {
Assert.notNull(encoder, "Encoder cannot be null.");
this.encoder = encoder;
}

View File

@ -2,6 +2,9 @@ package io.jsonwebtoken.io;
import io.jsonwebtoken.JwtException;
/**
* @since 0.10.0
*/
public class IOException extends JwtException {
public IOException(String msg) {

View File

@ -1,5 +1,8 @@
package io.jsonwebtoken.io;
/**
* @since 0.10.0
*/
public class SerialException extends IOException {
public SerialException(String msg) {

View File

@ -1,5 +1,8 @@
package io.jsonwebtoken.io;
/**
* @since 0.10.0
*/
public class SerializationException extends SerialException {
public SerializationException(String msg) {

View File

@ -1,5 +1,8 @@
package io.jsonwebtoken.io;
/**
* @since 0.10.0
*/
public interface Serializer<T> {
byte[] serialize(T t) throws SerializationException;

View File

@ -5,10 +5,7 @@ package io.jsonwebtoken.lang;
*/
public final class Arrays {
//for code coverage
private static final Arrays INSTANCE = new Arrays();
private Arrays(){}
private Arrays(){} //prevent instantiation
public static int length(byte[] bytes) {
return bytes != null ? bytes.length : 0;

View File

@ -20,10 +20,7 @@ import java.util.Map;
public final class Assert {
//for code coverage
private static final Assert INSTANCE = new Assert();
private Assert(){}
private Assert(){} //prevent instantiation
/**
* Assert a boolean expression, throwing <code>IllegalArgumentException</code>

View File

@ -23,9 +23,7 @@ import java.lang.reflect.Constructor;
*/
public final class Classes {
private static final Classes INSTANCE = new Classes();
private Classes() {}
private Classes() {} //prevent instantiation
/**
* @since 0.1
@ -137,6 +135,12 @@ public final class Classes {
return (T)newInstance(forName(fqcn));
}
public static <T> T newInstance(String fqcn, Class[] ctorArgTypes, Object... args) {
Class<T> clazz = forName(fqcn);
Constructor<T> ctor = getConstructor(clazz, ctorArgTypes);
return instantiate(ctor, args);
}
@SuppressWarnings("unchecked")
public static <T> T newInstance(String fqcn, Object... args) {
return (T)newInstance(forName(fqcn), args);

View File

@ -26,10 +26,7 @@ import java.util.Properties;
public final class Collections {
//for code coverage
private static final Collections INSTANCE = new Collections();
private Collections(){}
private Collections(){} //prevent instantiation
/**
* Return <code>true</code> if the supplied Collection is <code>null</code>

View File

@ -22,10 +22,7 @@ import java.util.Arrays;
public final class Objects {
//for code coverage
private static final Objects INSTANCE = new Objects();
private Objects(){}
private Objects(){} //prevent instantiation
private static final int INITIAL_HASH = 7;
private static final int MULTIPLIER = 31;

View File

@ -21,9 +21,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
public final class RuntimeEnvironment {
private static final RuntimeEnvironment INSTANCE = new RuntimeEnvironment();
private RuntimeEnvironment(){}
private RuntimeEnvironment(){} //prevent instantiation
private static final String BC_PROVIDER_CLASS_NAME = "org.bouncycastle.jce.provider.BouncyCastleProvider";
@ -33,7 +31,7 @@ public final class RuntimeEnvironment {
public static void enableBouncyCastleIfPossible() {
if (bcLoaded.get()) {
if (!BOUNCY_CASTLE_AVAILABLE || bcLoaded.get()) {
return;
}

View File

@ -31,8 +31,6 @@ import java.util.TreeSet;
public final class Strings {
private static final Strings INSTANCE = new Strings(); //for code coverage
private static final String FOLDER_SEPARATOR = "/";
private static final String WINDOWS_FOLDER_SEPARATOR = "\\";
@ -45,7 +43,7 @@ public final class Strings {
public static final Charset UTF_8 = Charset.forName("UTF-8");
private Strings(){}
private Strings(){} //prevent instantiation
//---------------------------------------------------------------------
// General convenience methods for working with Strings

View File

@ -0,0 +1,42 @@
package io.jsonwebtoken
import io.jsonwebtoken.lang.Classes
import org.junit.Test
import org.junit.runner.RunWith
import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.modules.junit4.PowerMockRunner
import static org.easymock.EasyMock.createMock
import static org.easymock.EasyMock.eq
import static org.easymock.EasyMock.expect
import static org.junit.Assert.assertSame
import static org.powermock.api.easymock.PowerMock.mockStatic
import static org.powermock.api.easymock.PowerMock.replay
import static org.powermock.api.easymock.PowerMock.verify
@RunWith(PowerMockRunner.class)
@PrepareForTest([Classes, CompressionCodecs])
class CompressionCodecsTest {
@Test
void testStatics() {
mockStatic(Classes)
def deflate = createMock(CompressionCodec)
def gzip = createMock(CompressionCodec)
expect(Classes.newInstance(eq("io.jsonwebtoken.impl.compression.DeflateCompressionCodec"))).andReturn(deflate)
expect(Classes.newInstance(eq("io.jsonwebtoken.impl.compression.GzipCompressionCodec"))).andReturn(gzip)
replay Classes, deflate, gzip
assertSame deflate, CompressionCodecs.DEFLATE
assertSame gzip, CompressionCodecs.GZIP
verify Classes, deflate, gzip
//test coverage for private constructor:
new CompressionCodecs()
}
}

View File

@ -24,17 +24,13 @@ class CompressionExceptionTest {
@Test
void testDefaultConstructor() {
def exception = new CompressionException("my message")
assertEquals "my message", exception.getMessage()
}
@Test
void testConstructorWithCause() {
def ioException = new IOException("root error")
def exception = new CompressionException("wrapping", ioException)
assertEquals "wrapping", exception.getMessage()
assertEquals ioException, exception.getCause()
}

View File

@ -16,19 +16,42 @@
package io.jsonwebtoken
import org.junit.Test
import static org.easymock.EasyMock.*
import static org.junit.Assert.*
class ExpiredJwtExceptionTest {
@Test
void testStringConstructor() {
def header = createMock(Header)
def claims = createMock(Claims)
def msg = 'foo'
replay header, claims
def ex = new ExpiredJwtException(header, claims, msg)
verify header, claims
assertSame ex.header, header
assertSame ex.claims, claims
assertEquals ex.message, msg
}
@Test
void testOverloadedConstructor() {
def header = Jwts.header()
def claims = Jwts.claims()
def header = createMock(Header)
def claims = createMock(Claims)
def msg = 'foo'
def cause = new NullPointerException()
replay header, claims
def ex = new ExpiredJwtException(header, claims, msg, cause)
verify header, claims
assertSame ex.header, header
assertSame ex.claims, claims
assertEquals ex.message, msg

View File

@ -17,25 +17,54 @@ package io.jsonwebtoken
import org.junit.Test
import static org.easymock.EasyMock.*
import static org.junit.Assert.assertEquals
import static org.junit.Assert.assertSame
class IncorrectClaimExceptionTest {
@Test
void testStringConstructor() {
def header = createMock(Header)
def claims = createMock(Claims)
def msg = 'foo'
def claimName = 'cName'
def claimValue = 'cValue'
replay header, claims
def ex = new IncorrectClaimException(header, claims, msg)
ex.setClaimName(claimName)
ex.setClaimValue(claimValue)
verify header, claims
assertSame ex.header, header
assertSame ex.claims, claims
assertEquals ex.message, msg
assertEquals ex.claimName, claimName
assertEquals ex.claimValue, claimValue
}
@Test
void testOverloadedConstructor() {
def header = Jwts.header()
def claims = Jwts.claims()
def header = createMock(Header)
def claims = createMock(Claims)
def msg = 'foo'
def cause = new NullPointerException()
def claimName = 'cName'
def claimValue = 'cValue'
replay header, claims
def ex = new IncorrectClaimException(header, claims, msg, cause)
ex.setClaimName(claimName)
ex.setClaimValue(claimValue)
verify header, claims
assertSame ex.header, header
assertSame ex.claims, claims
assertEquals ex.message, msg

View File

@ -17,6 +17,7 @@ package io.jsonwebtoken
import org.junit.Test
import static org.easymock.EasyMock.*
import static org.junit.Assert.assertEquals
import static org.junit.Assert.assertSame
@ -24,18 +25,22 @@ class InvalidClaimExceptionTest {
@Test
void testOverloadedConstructor() {
def header = Jwts.header()
def claims = Jwts.claims()
def header = createMock(Header)
def claims = createMock(Claims)
def msg = 'foo'
def cause = new NullPointerException()
def claimName = 'cName'
def claimValue = 'cValue'
replay header, claims
def ex = new InvalidClaimException(header, claims, msg, cause)
ex.setClaimName(claimName)
ex.setClaimValue(claimValue)
verify header, claims
assertSame ex.header, header
assertSame ex.claims, claims
assertEquals ex.message, msg

View File

@ -0,0 +1,182 @@
package io.jsonwebtoken
import io.jsonwebtoken.lang.Classes
import org.junit.Test
import org.junit.runner.RunWith
import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.modules.junit4.PowerMockRunner
import static org.easymock.EasyMock.createMock
import static org.easymock.EasyMock.eq
import static org.easymock.EasyMock.expect
import static org.easymock.EasyMock.same
import static org.junit.Assert.assertSame
import static org.powermock.api.easymock.PowerMock.mockStatic
import static org.powermock.api.easymock.PowerMock.replay
import static org.powermock.api.easymock.PowerMock.reset
import static org.powermock.api.easymock.PowerMock.verify
@RunWith(PowerMockRunner.class)
@PrepareForTest([Classes, Jwts])
class JwtsTest {
@Test
void testPrivateCtor() { //for code coverage only
new Jwts()
}
@Test
void testHeader() {
mockStatic(Classes)
def instance = createMock(Header)
expect(Classes.newInstance(eq("io.jsonwebtoken.impl.DefaultHeader"))).andReturn(instance)
replay Classes, instance
assertSame instance, Jwts.header()
verify Classes, instance
}
@Test
void testHeaderFromMap() {
mockStatic(Classes)
def map = [:]
def instance = createMock(Header)
expect(Classes.newInstance(
eq("io.jsonwebtoken.impl.DefaultHeader"),
same(Jwts.MAP_ARG),
same(map))
).andReturn(instance)
replay Classes, instance
assertSame instance, Jwts.header(map)
verify Classes, instance
}
@Test
void testJwsHeader() {
mockStatic(Classes)
def instance = createMock(JwsHeader)
expect(Classes.newInstance(eq("io.jsonwebtoken.impl.DefaultJwsHeader"))).andReturn(instance)
replay Classes, instance
assertSame instance, Jwts.jwsHeader()
verify Classes, instance
}
@Test
void testJwsHeaderFromMap() {
mockStatic(Classes)
def map = [:]
def instance = createMock(JwsHeader)
expect(Classes.newInstance(
eq("io.jsonwebtoken.impl.DefaultJwsHeader"),
same(Jwts.MAP_ARG),
same(map))
).andReturn(instance)
replay Classes, instance
assertSame instance, Jwts.jwsHeader(map)
verify Classes, instance
}
@Test
void testClaims() {
mockStatic(Classes)
def instance = createMock(Claims)
expect(Classes.newInstance(eq("io.jsonwebtoken.impl.DefaultClaims"))).andReturn(instance)
replay Classes, instance
assertSame instance, Jwts.claims()
verify Classes, instance
}
@Test
void testClaimsFromMap() {
mockStatic(Classes)
def map = [:]
def instance = createMock(Claims)
expect(Classes.newInstance(
eq("io.jsonwebtoken.impl.DefaultClaims"),
same(Jwts.MAP_ARG),
same(map))
).andReturn(instance)
replay Classes, instance
assertSame instance, Jwts.claims(map)
verify Classes, instance
}
@Test
void testParser() {
mockStatic(Classes)
def instance = createMock(JwtParser)
expect(Classes.newInstance(eq("io.jsonwebtoken.impl.DefaultJwtParser"))).andReturn(instance)
replay Classes, instance
assertSame instance, Jwts.parser()
verify Classes, instance
}
@Test
void testBuilder() {
mockStatic(Classes)
//JwtBuilder loads SignatureAlgorithm which in turn uses RuntimeEnvironment which in turn checks for BC:
expect(Classes.isAvailable(eq("org.bouncycastle.jce.provider.BouncyCastleProvider"))).andReturn(false)
replay Classes
def instance = createMock(JwtBuilder)
verify Classes
reset Classes
expect(Classes.newInstance(eq("io.jsonwebtoken.impl.DefaultJwtBuilder"))).andReturn(instance)
replay Classes, instance
assertSame instance, Jwts.builder()
verify Classes, instance
}
}

View File

@ -0,0 +1,22 @@
package io.jsonwebtoken
import org.junit.Test
import static org.junit.Assert.assertEquals
class MalformedJwtExceptionTest {
@Test
void testStringConstructor() {
def exception = new MalformedJwtException("my message")
assertEquals "my message", exception.getMessage()
}
@Test
void testCauseConstructor() {
def ioException = new IOException("root error")
def exception = new MalformedJwtException("wrapping", ioException)
assertEquals "wrapping", exception.getMessage()
assertEquals ioException, exception.getCause()
}
}

View File

@ -17,25 +17,54 @@ package io.jsonwebtoken
import org.junit.Test
import static org.easymock.EasyMock.*
import static org.junit.Assert.assertEquals
import static org.junit.Assert.assertSame
class MissingClaimExceptionTest {
@Test
void testStringConstructor() {
def header = createMock(Header)
def claims = createMock(Claims)
def msg = 'foo'
def claimName = 'cName'
def claimValue = 'cValue'
replay header, claims
def ex = new MissingClaimException(header, claims, msg)
ex.setClaimName(claimName)
ex.setClaimValue(claimValue)
verify header, claims
assertSame ex.header, header
assertSame ex.claims, claims
assertEquals ex.message, msg
assertEquals ex.claimName, claimName
assertEquals ex.claimValue, claimValue
}
@Test
void testOverloadedConstructor() {
def header = Jwts.header()
def claims = Jwts.claims()
def header = createMock(Header)
def claims = createMock(Claims)
def msg = 'foo'
def cause = new NullPointerException()
def claimName = 'cName'
def claimValue = 'cValue'
replay header, claims
def ex = new MissingClaimException(header, claims, msg, cause)
ex.setClaimName(claimName)
ex.setClaimValue(claimValue)
verify header, claims
assertSame ex.header, header
assertSame ex.claims, claims
assertEquals ex.message, msg

View File

@ -16,19 +16,42 @@
package io.jsonwebtoken
import org.junit.Test
import static org.easymock.EasyMock.*
import static org.junit.Assert.*
class PrematureJwtExceptionTest {
@Test
void testStringConstructor() {
def header = createMock(Header)
def claims = createMock(Claims)
def msg = 'foo'
replay header, claims
def ex = new PrematureJwtException(header, claims, msg)
verify header, claims
assertSame ex.header, header
assertSame ex.claims, claims
assertEquals ex.message, msg
}
@Test
void testOverloadedConstructor() {
def header = Jwts.header()
def claims = Jwts.claims()
def header = createMock(Header)
def claims = createMock(Claims)
def msg = 'foo'
def cause = new NullPointerException()
replay header, claims
def ex = new PrematureJwtException(header, claims, msg, cause)
verify header, claims
assertSame ex.header, header
assertSame ex.claims, claims
assertEquals ex.message, msg

View File

@ -6,15 +6,20 @@ import static org.junit.Assert.assertEquals
import static org.junit.Assert.assertSame
class RequiredTypeExceptionTest {
@Test
void testStringConstructor() {
def msg = 'foo'
def ex = new RequiredTypeException(msg)
assertEquals ex.message, msg
}
@Test
void testOverloadedConstructor() {
def msg = 'foo'
def cause = new NullPointerException()
def ex = new RequiredTypeException(msg, cause)
assertEquals ex.message, msg
assertSame ex.cause, cause
}
}

View File

@ -0,0 +1,22 @@
package io.jsonwebtoken
import org.junit.Test
import static org.junit.Assert.assertEquals
class SignatureExceptionTest {
@Test
void testStringConstructor() {
def exception = new SignatureException("my message")
assertEquals "my message", exception.getMessage()
}
@Test
void testCauseConstructor() {
def ioException = new IOException("root error")
def exception = new SignatureException("wrapping", ioException)
assertEquals "wrapping", exception.getMessage()
assertEquals ioException, exception.getCause()
}
}

View File

@ -0,0 +1,102 @@
package io.jsonwebtoken
import org.junit.Test
import javax.crypto.spec.SecretKeySpec
import static org.easymock.EasyMock.*
import static org.junit.Assert.*
class SigningKeyResolverAdapterTest {
@Test(expected=UnsupportedJwtException) //should throw since called but not overridden
void testDefaultResolveSigningKeyBytesFromClaims() {
def header = createMock(JwsHeader)
def claims = createMock(Claims)
new SigningKeyResolverAdapter().resolveSigningKeyBytes(header, claims)
}
@Test(expected=UnsupportedJwtException) //should throw since called but not overridden
void testDefaultResolveSigningKeyBytesFromStringPayload() {
def header = createMock(JwsHeader)
new SigningKeyResolverAdapter().resolveSigningKeyBytes(header, "hi")
}
@Test
void testResolveSigningKeyHmac() {
JwsHeader header = createMock(JwsHeader)
Claims claims = createMock(Claims)
byte[] bytes = new byte[32]
new Random().nextBytes(bytes)
expect(header.getAlgorithm()).andReturn("HS256")
replay header, claims
def adapter = new SigningKeyResolverAdapter() {
@Override
byte[] resolveSigningKeyBytes(JwsHeader h, Claims c) {
assertSame header, h
assertSame claims, c
return bytes
}
}
def key = adapter.resolveSigningKey(header, claims)
verify header, claims
assertTrue key instanceof SecretKeySpec
assertEquals 'HmacSHA256', key.algorithm
assertTrue Arrays.equals(bytes, key.encoded)
}
@Test(expected=IllegalArgumentException)
void testResolveSigningKeyDefaultWithoutHmac() {
JwsHeader header = createMock(JwsHeader)
Claims claims = createMock(Claims)
expect(header.getAlgorithm()).andReturn("RS256")
replay header, claims
new SigningKeyResolverAdapter().resolveSigningKey(header, claims)
}
@Test
void testResolveSigningKeyPayloadHmac() {
JwsHeader header = createMock(JwsHeader)
byte[] bytes = new byte[32]
new Random().nextBytes(bytes)
expect(header.getAlgorithm()).andReturn("HS256")
replay header
def adapter = new SigningKeyResolverAdapter() {
@Override
byte[] resolveSigningKeyBytes(JwsHeader h, String s) {
assertSame header, h
assertEquals 'hi', s
return bytes
}
}
def key = adapter.resolveSigningKey(header, 'hi')
verify header
assertTrue key instanceof SecretKeySpec
assertEquals 'HmacSHA256', key.algorithm
assertTrue Arrays.equals(bytes, key.encoded)
}
@Test(expected=IllegalArgumentException)
void testResolveSigningKeyPayloadWithoutHmac() {
JwsHeader header = createMock(JwsHeader)
expect(header.getAlgorithm()).andReturn("RS256")
replay header
new SigningKeyResolverAdapter().resolveSigningKey(header, 'hi')
}
}

View File

@ -0,0 +1,22 @@
package io.jsonwebtoken
import org.junit.Test
import static org.junit.Assert.assertEquals
class UnsupportedJwtExceptionTest {
@Test
void testStringConstructor() {
def exception = new UnsupportedJwtException("my message")
assertEquals "my message", exception.getMessage()
}
@Test
void testCauseConstructor() {
def ioException = new IOException("root error")
def exception = new UnsupportedJwtException("wrapping", ioException)
assertEquals "wrapping", exception.getMessage()
assertEquals ioException, exception.getCause()
}
}

View File

@ -1,4 +1,4 @@
package io.jsonwebtoken.codec.impl
package io.jsonwebtoken.io
import io.jsonwebtoken.lang.Strings
import org.junit.Test

View File

@ -1,4 +1,4 @@
package io.jsonwebtoken.codec.impl
package io.jsonwebtoken.io
import io.jsonwebtoken.lang.Strings
import org.junit.Test

View File

@ -1,4 +1,4 @@
package io.jsonwebtoken.codec.impl
package io.jsonwebtoken.io
import io.jsonwebtoken.lang.Strings
import org.junit.Test
@ -82,60 +82,86 @@ class Base64Test {
assertEquals PLAINTEXT, new String(resultBytes, Strings.UTF_8)
}
private static String BASE64(String s) {
private static String encode(String s) {
byte[] bytes = s.getBytes(Strings.UTF_8);
return Base64.DEFAULT.encodeToString(bytes, false)
}
private static String decode(String s) {
byte[] bytes = Base64.DEFAULT.decodeFast(s.toCharArray())
return new String(bytes, Strings.UTF_8)
}
@Test // https://tools.ietf.org/html/rfc4648#page-12
void testRfc4648Base64TestVectors() {
assertEquals "", BASE64("")
assertEquals "", encode("")
assertEquals "", decode("")
assertEquals "Zg==", BASE64("f")
assertEquals "Zg==", encode("f")
assertEquals "f", decode("Zg==")
assertEquals "Zm8=", BASE64("fo")
assertEquals "Zm8=", encode("fo")
assertEquals "fo", decode("Zm8=")
assertEquals "Zm9v", BASE64("foo")
assertEquals "Zm9v", encode("foo")
assertEquals "foo", decode("Zm9v")
assertEquals "Zm9vYg==", BASE64("foob")
assertEquals "Zm9vYg==", encode("foob")
assertEquals "foob", decode("Zm9vYg==")
assertEquals "Zm9vYmE=", BASE64("fooba")
assertEquals "Zm9vYmE=", encode("fooba")
assertEquals "fooba", decode("Zm9vYmE=")
assertEquals "Zm9vYmFy", BASE64("foobar")
assertEquals "Zm9vYmFy", encode("foobar")
assertEquals "foobar", decode("Zm9vYmFy")
def input = 'special: [\r\n \t], ascii[32..126]: [ !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~]\n'
def expected = "c3BlY2lhbDogWw0KIAldLCBhc2NpaVszMi4uMTI2XTogWyAhIiMkJSYnKCkqKywtLi8wMTIzNDU2Nzg5Ojs8PT4/QEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaW1xdXl9gYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH1+XQo="
assertEquals expected, BASE64(input)
assertEquals expected, encode(input)
assertEquals input, decode(expected)
}
private static String BASE64URL(String s) {
private static String urlEncode(String s) {
byte[] bytes = s.getBytes(Strings.UTF_8);
return Base64.URL_SAFE.encodeToString(bytes, false)
}
private static String urlDecode(String s) {
byte[] bytes = Base64.URL_SAFE.decodeFast(s.toCharArray())
return new String(bytes, Strings.UTF_8)
}
@Test //same test vectors above, but with padding removed & some specials swapped: https://brockallen.com/2014/10/17/base64url-encoding/
void testRfc4648Base64UrlTestVectors() {
assertEquals "", BASE64URL("")
assertEquals "", urlEncode("")
assertEquals "", urlDecode("")
assertEquals "Zg", BASE64URL("f") //base64 = 2 padding chars, base64url = no padding needed
assertEquals "Zg", urlEncode("f") //base64 = 2 padding chars, base64url = no padding needed
assertEquals "f", urlDecode("Zg")
assertEquals "Zm8", BASE64URL("fo") //base64 = 1 padding char, base64url = no padding needed
assertEquals "Zm8", urlEncode("fo") //base64 = 1 padding char, base64url = no padding needed
assertEquals "fo", urlDecode("Zm8")
assertEquals "Zm9v", BASE64URL("foo")
assertEquals "Zm9v", urlEncode("foo")
assertEquals "foo", urlDecode("Zm9v")
assertEquals "Zm9vYg", BASE64URL("foob") //base64 = 2 padding chars, base64url = no padding needed
assertEquals "Zm9vYg", urlEncode("foob") //base64 = 2 padding chars, base64url = no padding needed
assertEquals "foob", urlDecode("Zm9vYg")
assertEquals "Zm9vYmE", BASE64URL("fooba") //base64 = 1 padding char, base64url = no padding needed
assertEquals "Zm9vYmE", urlEncode("fooba") //base64 = 1 padding char, base64url = no padding needed
assertEquals "fooba", urlDecode("Zm9vYmE")
assertEquals "Zm9vYmFy", BASE64URL("foobar")
assertEquals "Zm9vYmFy", urlEncode("foobar")
assertEquals "foobar", urlDecode("Zm9vYmFy")
def input = 'special: [\r\n \t], ascii[32..126]: [ !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~]\n'
def expected = "c3BlY2lhbDogWw0KIAldLCBhc2NpaVszMi4uMTI2XTogWyAhIiMkJSYnKCkqKywtLi8wMTIzNDU2Nzg5Ojs8PT4/QEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaW1xdXl9gYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH1+XQo="
.replace("=", "")
.replace("+", "-")
.replace("/", "_")
assertEquals expected, BASE64URL(input)
assertEquals expected, urlEncode(input)
assertEquals input, urlDecode(expected)
}
}

View File

@ -1,4 +1,4 @@
package io.jsonwebtoken.codec
package io.jsonwebtoken.io
import org.junit.Test
@ -8,7 +8,7 @@ class CodecExceptionTest {
@Test
void testConstructorWithCause() {
def ioException = new IOException("root error")
def ioException = new java.io.IOException("root error")
def exception = new CodecException("wrapping", ioException)
assertEquals "wrapping", exception.getMessage()
assertEquals ioException, exception.getCause()

View File

@ -0,0 +1,22 @@
package io.jsonwebtoken.io
import org.junit.Test
import static org.junit.Assert.*
class DecodersTest {
@Test
void testBase64() {
new Decoders() //not allowed in java, including here only to pass test coverage assertions
assertTrue Decoders.BASE64 instanceof ExceptionPropagatingDecoder
assertTrue Decoders.BASE64.decoder instanceof Base64Decoder
}
@Test
void testBase64Url() {
assertTrue Decoders.BASE64URL instanceof ExceptionPropagatingDecoder
assertTrue Decoders.BASE64URL.decoder instanceof Base64UrlDecoder
}
}

View File

@ -1,4 +1,4 @@
package io.jsonwebtoken.codec
package io.jsonwebtoken.io
import org.junit.Test
@ -8,7 +8,7 @@ class DecodingExceptionTest {
@Test
void testConstructorWithCause() {
def ioException = new IOException("root error")
def ioException = new java.io.IOException("root error")
def exception = new DecodingException("wrapping", ioException)
assertEquals "wrapping", exception.getMessage()
assertEquals ioException, exception.getCause()

View File

@ -0,0 +1,22 @@
package io.jsonwebtoken.io
import org.junit.Test
import static org.junit.Assert.assertEquals
class DeserializationExceptionTest {
@Test
void testDefaultConstructor() {
def exception = new DeserializationException("my message")
assertEquals "my message", exception.getMessage()
}
@Test
void testConstructorWithCause() {
def ioException = new java.io.IOException("root error")
def exception = new DeserializationException("wrapping", ioException)
assertEquals "wrapping", exception.getMessage()
assertEquals ioException, exception.getCause()
}
}

View File

@ -0,0 +1,21 @@
package io.jsonwebtoken.io
import org.junit.Test
import static org.junit.Assert.*
class EncodersTest {
@Test
void testBase64() {
new Encoders() //not allowed in java, including here only to pass test coverage assertions
assertTrue Encoders.BASE64 instanceof ExceptionPropagatingEncoder
assertTrue Encoders.BASE64.encoder instanceof Base64Encoder
}
@Test
void testBase64Url() {
assertTrue Encoders.BASE64URL instanceof ExceptionPropagatingEncoder
assertTrue Encoders.BASE64URL.encoder instanceof Base64UrlEncoder
}
}

View File

@ -1,4 +1,4 @@
package io.jsonwebtoken.codec
package io.jsonwebtoken.io
import org.junit.Test
@ -8,7 +8,7 @@ class EncodingExceptionTest {
@Test
void testConstructorWithCause() {
def ioException = new IOException("root error")
def ioException = new java.io.IOException("root error")
def exception = new EncodingException("wrapping", ioException)
assertEquals "wrapping", exception.getMessage()
assertEquals ioException, exception.getCause()

View File

@ -1,8 +1,5 @@
package io.jsonwebtoken.codec.impl
package io.jsonwebtoken.io
import io.jsonwebtoken.codec.Decoder
import io.jsonwebtoken.codec.DecodingException
import io.jsonwebtoken.codec.EncodingException
import org.junit.Test
import static org.junit.Assert.*
@ -25,7 +22,7 @@ class ExceptionPropagatingDecoderTest {
def decoder = new ExceptionPropagatingDecoder(new Decoder() {
@Override
Object decode(Object o) throws DecodingException {
throw new DecodingException("problem", new IOException("dummy"))
throw new DecodingException("problem", new java.io.IOException("dummy"))
}
})
try {

View File

@ -1,7 +1,5 @@
package io.jsonwebtoken.codec.impl
package io.jsonwebtoken.io
import io.jsonwebtoken.codec.Encoder
import io.jsonwebtoken.codec.EncodingException
import org.junit.Test
import static org.junit.Assert.*
@ -25,7 +23,7 @@ class ExceptionPropagatingEncoderTest {
def encoder = new ExceptionPropagatingEncoder(new Encoder() {
@Override
Object encode(Object o) throws EncodingException {
throw new EncodingException("problem", new IOException("dummy"))
throw new EncodingException("problem", new java.io.IOException("dummy"))
}
})
try {

View File

@ -0,0 +1,22 @@
package io.jsonwebtoken.io
import org.junit.Test
import static org.junit.Assert.assertEquals
class SerializationExceptionTest {
@Test
void testDefaultConstructor() {
def exception = new SerializationException("my message")
assertEquals "my message", exception.getMessage()
}
@Test
void testConstructorWithCause() {
def ioException = new java.io.IOException("root error")
def exception = new SerializationException("wrapping", ioException)
assertEquals "wrapping", exception.getMessage()
assertEquals ioException, exception.getCause()
}
}

48
core/pom.xml Normal file
View File

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2018 JWTK
~
~ 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-root</artifactId>
<version>0.10.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>jjwt-core</artifactId>
<name>JJWT :: Core</name>
<packaging>jar</packaging>
<properties>
<jjwt.root>${basedir}/..</jjwt.root>
</properties>
<dependencies>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2018 JWTK
~
~ 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-root</artifactId>
<version>0.10.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>jjwt-jackson</artifactId>
<name>JJWT :: Extensions :: Jackson</name>
<packaging>jar</packaging>
<properties>
<jjwt.root>${basedir}/../..</jjwt.root>
</properties>
<dependencies>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -1,14 +1,13 @@
package io.jsonwebtoken.io.impl.jackson;
package io.jsonwebtoken.io;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.io.DeserializationException;
import io.jsonwebtoken.io.Deserializer;
import io.jsonwebtoken.lang.Assert;
import java.io.IOException;
import java.util.Map;
@SuppressWarnings("unused") //used via reflection by RuntimeClasspathDeserializerLocator
/**
* @since 0.10.0
*/
public class JacksonDeserializer<T> implements Deserializer<T> {
private final Class<T> returnType;
@ -21,7 +20,7 @@ public class JacksonDeserializer<T> implements Deserializer<T> {
@SuppressWarnings({"unchecked", "WeakerAccess", "unused"}) // for end-users providing a custom ObjectMapper
public JacksonDeserializer(ObjectMapper objectMapper) {
this(objectMapper, (Class<T>) Map.class);
this(objectMapper, (Class<T>) Object.class);
}
private JacksonDeserializer(ObjectMapper objectMapper, Class<T> returnType) {

View File

@ -1,11 +1,12 @@
package io.jsonwebtoken.io.impl.jackson;
package io.jsonwebtoken.io;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.io.SerializationException;
import io.jsonwebtoken.io.Serializer;
import io.jsonwebtoken.lang.Assert;
/**
* @since 0.10.0
*/
public class JacksonSerializer<T> implements Serializer<T> {
static final ObjectMapper DEFAULT_OBJECT_MAPPER = new ObjectMapper();

View File

@ -1,14 +1,10 @@
package io.jsonwebtoken.io.impl.jackson
package io.jsonwebtoken.io
import com.fasterxml.jackson.databind.ObjectMapper
import io.jsonwebtoken.io.DeserializationException
import io.jsonwebtoken.lang.Strings
import org.junit.Test
import static org.easymock.EasyMock.createMock
import static org.easymock.EasyMock.expect
import static org.easymock.EasyMock.replay
import static org.easymock.EasyMock.verify
import static org.easymock.EasyMock.*
import static org.junit.Assert.*
class JacksonDeserializerTest {
@ -42,13 +38,13 @@ class JacksonDeserializerTest {
@Test
void testDeserializeFailsWithJsonProcessingException() {
def ex = createMock(IOException)
def ex = createMock(java.io.IOException)
expect(ex.getMessage()).andReturn('foo')
def deserializer = new JacksonDeserializer() {
@Override
protected Object readValue(byte[] bytes) throws IOException {
protected Object readValue(byte[] bytes) throws java.io.IOException {
throw ex
}
}
@ -59,7 +55,7 @@ class JacksonDeserializerTest {
deserializer.deserialize('{"hello":"世界"}'.getBytes(Strings.UTF_8))
fail()
} catch (DeserializationException se) {
assertEquals 'Unable to deserialize bytes into a java.util.Map instance: foo', se.getMessage()
assertEquals 'Unable to deserialize bytes into a java.lang.Object instance: foo', se.getMessage()
assertSame ex, se.getCause()
}

View File

@ -1,16 +1,11 @@
package io.jsonwebtoken.io.impl.jackson
package io.jsonwebtoken.io
import com.fasterxml.jackson.core.JsonProcessingException
import com.fasterxml.jackson.databind.ObjectMapper
import io.jsonwebtoken.codec.Encoder
import io.jsonwebtoken.io.SerializationException
import io.jsonwebtoken.lang.Strings
import org.junit.Test
import static org.easymock.EasyMock.createMock
import static org.easymock.EasyMock.expect
import static org.easymock.EasyMock.replay
import static org.easymock.EasyMock.verify
import static org.easymock.EasyMock.*
import static org.junit.Assert.*
class JacksonSerializerTest {
@ -44,8 +39,7 @@ class JacksonSerializerTest {
@Test
void testByteArray() { //expect Base64 string by default:
byte[] bytes = "hi".getBytes(Strings.UTF_8)
String encoded = Encoder.BASE64.encode(bytes)
String expected = "\"$encoded\"" as String
String expected = '"aGk="' as String //base64(hi) --> aGk=
byte[] result = new JacksonSerializer().serialize(bytes)
assertEquals expected, new String(result, Strings.UTF_8)
}
@ -53,10 +47,8 @@ class JacksonSerializerTest {
@Test
void testEmptyByteArray() { //expect Base64 string by default:
byte[] bytes = new byte[0]
String encoded = Encoder.BASE64.encode(bytes)
String expected = "\"$encoded\"" as String
byte[] result = new JacksonSerializer().serialize(bytes)
assertEquals expected, new String(result, Strings.UTF_8)
assertEquals '""', new String(result, Strings.UTF_8)
}
@Test

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2018 JWTK
~
~ 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-root</artifactId>
<version>0.10.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>jjwt-orgjson</artifactId>
<name>JJWT :: Extensions :: org.json</name>
<packaging>jar</packaging>
<properties>
<jjwt.root>${basedir}/../..</jjwt.root>
</properties>
<dependencies>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
</dependency>
</dependencies>
</project>

Some files were not shown because too many files have changed in this diff Show More