Add Problem object for JSON problem documents

Backport of commit 4e1d173c, fdc05ba7
pull/38/head
Richard Körber 2017-09-11 19:06:03 +02:00
parent beb7c8b745
commit 658bfa2cda
5 changed files with 150 additions and 2 deletions

View File

@ -0,0 +1,70 @@
/*
* acme4j - Java ACME client
*
* Copyright (C) 2017 Richard "Shred" Körber
* http://acme4j.shredzone.org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
package org.shredzone.acme4j;
import java.io.Serializable;
import java.net.URI;
import org.shredzone.acme4j.util.JSON;
/**
* Represents a JSON Problem.
*
* @see <a href="https://tools.ietf.org/html/rfc7807">RFC 7807</a>
*/
public class Problem implements Serializable {
private static final long serialVersionUID = -8418248862966754214L;
private final JSON problemJson;
/**
* Creates a new {@link Problem} object.
*
* @param problem
* Problem as JSON structure
*/
public Problem(JSON problem) {
this.problemJson = problem;
}
/**
* Returns the problem type.
*/
public URI getType() {
return problemJson.get("type").asURI();
}
/**
* Returns a human-readable description of the problem.
*/
public String getDetail() {
return problemJson.get("detail").asString();
}
/**
* Returns the problem as {@link JSON} object, to access other fields.
*/
public JSON asJSON() {
return problemJson;
}
/**
* Returns the problem as JSON string.
*/
@Override
public String toString() {
return problemJson.toString();
}
}

View File

@ -41,6 +41,7 @@ import java.util.stream.StreamSupport;
import org.jose4j.json.JsonUtil;
import org.jose4j.lang.JoseException;
import org.shredzone.acme4j.Problem;
import org.shredzone.acme4j.exception.AcmeProtocolException;
/**
@ -294,6 +295,19 @@ public final class JSON implements Serializable {
}
}
/**
* Returns the value as {@link Problem}.
*
* @return {@link Problem}, or {@code null} if the value was not set.
*/
public Problem asProblem() {
if (val == null) {
return null;
}
return new Problem(asObject());
}
/**
* Returns the value as JSON array.
*

View File

@ -0,0 +1,43 @@
/*
* acme4j - Java ACME client
*
* Copyright (C) 2017 Richard "Shred" Körber
* http://acme4j.shredzone.org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
package org.shredzone.acme4j;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs;
import java.net.URI;
import org.junit.Test;
import org.shredzone.acme4j.util.JSON;
import org.shredzone.acme4j.util.TestUtils;
/**
* Unit tests for {@link Problem}.
*/
public class ProblemTest {
@Test
public void testProblem() {
JSON original = TestUtils.getJsonAsObject("problem");
Problem problem = new Problem(original);
assertThat(problem.getType(), is(URI.create("urn:ietf:params:acme:error:connection")));
assertThat(problem.getDetail(), is("connection refused"));
assertThat(problem.asJSON().toString(), is(sameJSONAs(original.toString())));
assertThat(problem.toString(), is(sameJSONAs(original.toString())));
}
}

View File

@ -36,6 +36,7 @@ import java.util.NoSuchElementException;
import java.util.stream.Collectors;
import org.junit.Test;
import org.shredzone.acme4j.Problem;
import org.shredzone.acme4j.exception.AcmeProtocolException;
/**
@ -84,7 +85,7 @@ public class JSONTest {
JSON json = TestUtils.getJsonAsObject("json");
assertThat(json.keySet(), containsInAnyOrder(
"text", "number", "uri", "url", "date", "array", "collect"));
"text", "number", "uri", "url", "date", "array", "collect", "problem"));
assertThat(json.contains("text"), is(true));
assertThat(json.contains("music"), is(false));
assertThat(json.get("text"), is(notNullValue()));
@ -189,6 +190,11 @@ public class JSONTest {
JSON sub = array.get(3).asObject();
assertThat(sub.get("test").asString(), is("ok"));
Problem problem = json.get("problem").asProblem();
assertThat(problem, is(notNullValue()));
assertThat(problem.getType(), is(URI.create("urn:ietf:params:acme:error:rateLimited")));
assertThat(problem.getDetail(), is("too many requests"));
}
/**
@ -205,6 +211,7 @@ public class JSONTest {
assertThat(json.get("none").asInstant(), is(nullValue()));
assertThat(json.get("none").asArray(), is(nullValue()));
assertThat(json.get("none").asObject(), is(nullValue()));
assertThat(json.get("none").asProblem(), is(nullValue()));
try {
json.get("none").asInt();
@ -272,6 +279,13 @@ public class JSONTest {
} catch (AcmeProtocolException ex) {
// expected
}
try {
json.get("text").asProblem();
fail("no exception was thrown");
} catch (AcmeProtocolException ex) {
// expected
}
}
/**

View File

@ -42,7 +42,14 @@ json = \
"url": "http://example.com",\
"date": "2016-01-08T00:00:00Z",\
"array": ["foo", 987, [1, 2, 3], {"test": "ok"}],\
"collect": ["foo", "bar", "barfoo"]\
"collect": ["foo", "bar", "barfoo"],\
"problem": {"type": "urn:ietf:params:acme:error:rateLimited", "detail": "too many requests"}\
}
problem = \
{\
"type": "urn:ietf:params:acme:error:connection",\
"detail": "connection refused"\
}
newRegistration = \