mirror of https://github.com/shred/acme4j
Replace all JSON maps with a JSON type
parent
0ee546da8b
commit
101801260f
|
@ -22,13 +22,13 @@ import java.util.Arrays;
|
|||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.shredzone.acme4j.challenge.Challenge;
|
||||
import org.shredzone.acme4j.connector.Connection;
|
||||
import org.shredzone.acme4j.exception.AcmeException;
|
||||
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
||||
import org.shredzone.acme4j.exception.AcmeRetryAfterException;
|
||||
import org.shredzone.acme4j.util.JSON;
|
||||
import org.shredzone.acme4j.util.JSONBuilder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -180,7 +180,7 @@ public class Authorization extends AcmeResource {
|
|||
conn.sendRequest(getLocation(), getSession());
|
||||
int rc = conn.accept(HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_ACCEPTED);
|
||||
|
||||
Map<String, Object> result = conn.readJsonResponse();
|
||||
JSON result = conn.readJsonResponse();
|
||||
unmarshalAuthorization(result);
|
||||
|
||||
if (rc == HttpURLConnection.HTTP_ACCEPTED) {
|
||||
|
@ -231,43 +231,42 @@ public class Authorization extends AcmeResource {
|
|||
* @param json
|
||||
* JSON data
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void unmarshalAuthorization(Map<String, Object> json) {
|
||||
this.status = Status.parse((String) json.get("status"), Status.PENDING);
|
||||
protected void unmarshalAuthorization(JSON json) {
|
||||
this.status = Status.parse(json.get("status").asString(), Status.PENDING);
|
||||
|
||||
String jsonExpires = (String) json.get("expires");
|
||||
String jsonExpires = json.get("expires").asString();
|
||||
if (jsonExpires != null) {
|
||||
expires = parseTimestamp(jsonExpires);
|
||||
}
|
||||
|
||||
Map<String, Object> jsonIdentifier = (Map<String, Object>) json.get("identifier");
|
||||
JSON jsonIdentifier = json.get("identifier").asObject();
|
||||
if (jsonIdentifier != null) {
|
||||
String type = (String) jsonIdentifier.get("type");
|
||||
String type = jsonIdentifier.get("type").asString();
|
||||
if (type != null && !"dns".equals(type)) {
|
||||
throw new AcmeProtocolException("Unknown authorization type: " + type);
|
||||
}
|
||||
domain = (String) jsonIdentifier.get("value");
|
||||
domain = jsonIdentifier.get("value").asString();
|
||||
}
|
||||
|
||||
Collection<Map<String, Object>> jsonChallenges =
|
||||
(Collection<Map<String, Object>>) json.get("challenges");
|
||||
JSON.Array jsonChallenges = json.get("challenges").asArray();
|
||||
List<Challenge> cr = new ArrayList<>();
|
||||
for (Map<String, Object> c : jsonChallenges) {
|
||||
Challenge ch = getSession().createChallenge(c);
|
||||
for (JSON.Value c : jsonChallenges) {
|
||||
Challenge ch = getSession().createChallenge(c.asObject());
|
||||
if (ch != null) {
|
||||
cr.add(ch);
|
||||
}
|
||||
}
|
||||
challenges = cr;
|
||||
|
||||
Collection<List<Number>> jsonCombinations =
|
||||
(Collection<List<Number>>) json.get("combinations");
|
||||
JSON.Array jsonCombinations = json.get("combinations").asArray();
|
||||
if (jsonCombinations != null) {
|
||||
List<List<Challenge>> cmb = new ArrayList<>(jsonCombinations.size());
|
||||
for (List<Number> c : jsonCombinations) {
|
||||
|
||||
for (int ix = 0; ix < jsonCombinations.size(); ix++) {
|
||||
JSON.Array c = jsonCombinations.get(ix).asArray();
|
||||
List<Challenge> clist = new ArrayList<>(c.size());
|
||||
for (Number n : c) {
|
||||
clist.add(cr.get(n.intValue()));
|
||||
for (JSON.Value n : c) {
|
||||
clist.add(cr.get(n.asInt()));
|
||||
}
|
||||
cmb.add(clist);
|
||||
}
|
||||
|
|
|
@ -14,26 +14,20 @@
|
|||
package org.shredzone.acme4j;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
|
||||
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
||||
import org.shredzone.acme4j.util.JSON;
|
||||
import org.shredzone.acme4j.util.JSON.Array;
|
||||
import org.shredzone.acme4j.util.JSON.Value;
|
||||
|
||||
/**
|
||||
* Contains metadata related to the provider.
|
||||
*/
|
||||
public class Metadata {
|
||||
|
||||
private final Map<String, Object> meta;
|
||||
|
||||
/**
|
||||
* Creates an empty new {@link Metadata} instance.
|
||||
*/
|
||||
public Metadata() {
|
||||
this(new HashMap<String, Object>());
|
||||
}
|
||||
private final JSON meta;
|
||||
|
||||
/**
|
||||
* Creates a new {@link Metadata} instance.
|
||||
|
@ -41,7 +35,7 @@ public class Metadata {
|
|||
* @param meta
|
||||
* JSON map of metadata
|
||||
*/
|
||||
public Metadata(Map<String, Object> meta) {
|
||||
public Metadata(JSON meta) {
|
||||
this.meta = meta;
|
||||
}
|
||||
|
||||
|
@ -50,7 +44,7 @@ public class Metadata {
|
|||
* available.
|
||||
*/
|
||||
public URI getTermsOfService() {
|
||||
return getUri("terms-of-service");
|
||||
return meta.get("terms-of-service").asURI();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -58,73 +52,31 @@ public class Metadata {
|
|||
* server. {@code null} if not available.
|
||||
*/
|
||||
public URI getWebsite() {
|
||||
return getUri("website");
|
||||
return meta.get("website").asURI();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of hostnames, which the ACME server recognises as referring to
|
||||
* Returns a collection of hostnames, which the ACME server recognises as referring to
|
||||
* itself for the purposes of CAA record validation. {@code null} if not available.
|
||||
*/
|
||||
public String[] getCaaIdentities() {
|
||||
return getStringArray("caa-identities");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a custom metadata value, as {@link String}.
|
||||
*
|
||||
* @param key
|
||||
* Key of the meta value
|
||||
* @return Value as {@link String}, or {@code null} if there is no such key in the
|
||||
* directory metadata.
|
||||
*/
|
||||
public String get(String key) {
|
||||
Object value = meta.get(key);
|
||||
return value != null ? value.toString() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a custom metadata value, as {@link URI}.
|
||||
*
|
||||
* @param key
|
||||
* Key of the meta value
|
||||
* @return Value as {@link URI}, or {@code null} if there is no such key in the
|
||||
* directory metadata.
|
||||
* @throws AcmeProtocolException
|
||||
* if the value is not an {@link URI}
|
||||
*/
|
||||
public URI getUri(String key) {
|
||||
Object uri = meta.get(key);
|
||||
try {
|
||||
return uri != null ? new URI(uri.toString()) : null;
|
||||
} catch (URISyntaxException ex) {
|
||||
throw new AcmeProtocolException("Bad URI: " + uri, ex);
|
||||
public Collection<String> getCaaIdentities() {
|
||||
Array array = meta.get("caa-identities").asArray();
|
||||
if (array == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a custom metadata value, as array of {@link String}.
|
||||
*
|
||||
* @param key
|
||||
* Key of the meta value
|
||||
* @return {@link String} array, or {@code null} if there is no such key in the
|
||||
* directory metadata.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public String[] getStringArray(String key) {
|
||||
Object value = meta.get(key);
|
||||
if (value != null && value instanceof Collection) {
|
||||
Collection<String> data = (Collection<String>) value;
|
||||
return data.toArray(new String[data.size()]);
|
||||
List<String> result = new ArrayList<>(array.size());
|
||||
for (Value v : array) {
|
||||
result.add(v.asString());
|
||||
}
|
||||
return null;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the metadata as raw JSON map.
|
||||
* <p>
|
||||
* Do not modify the map or its contents. Changes will have a session-wide effect.
|
||||
* Returns the JSON representation of the metadata. This is useful for reading
|
||||
* proprietary metadata properties.
|
||||
*/
|
||||
public Map<String, Object> getJsonData() {
|
||||
public JSON getJSON() {
|
||||
return meta;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,17 +17,14 @@ import static org.shredzone.acme4j.util.AcmeUtils.*;
|
|||
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.security.KeyPair;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.jose4j.jwk.PublicJsonWebKey;
|
||||
|
@ -39,6 +36,7 @@ import org.shredzone.acme4j.connector.ResourceIterator;
|
|||
import org.shredzone.acme4j.exception.AcmeException;
|
||||
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
||||
import org.shredzone.acme4j.exception.AcmeRetryAfterException;
|
||||
import org.shredzone.acme4j.util.JSON;
|
||||
import org.shredzone.acme4j.util.JSONBuilder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -162,7 +160,7 @@ public class Registration extends AcmeResource {
|
|||
conn.sendSignedRequest(getLocation(), claims, getSession());
|
||||
conn.accept(HttpURLConnection.HTTP_CREATED, HttpURLConnection.HTTP_ACCEPTED);
|
||||
|
||||
Map<String, Object> json = conn.readJsonResponse();
|
||||
JSON json = conn.readJsonResponse();
|
||||
unmarshal(json, conn);
|
||||
}
|
||||
}
|
||||
|
@ -193,7 +191,7 @@ public class Registration extends AcmeResource {
|
|||
conn.sendSignedRequest(getSession().resourceUri(Resource.NEW_AUTHZ), claims, getSession());
|
||||
conn.accept(HttpURLConnection.HTTP_CREATED);
|
||||
|
||||
Map<String, Object> json = conn.readJsonResponse();
|
||||
JSON json = conn.readJsonResponse();
|
||||
|
||||
Authorization auth = new Authorization(getSession(), conn.getLocation());
|
||||
auth.unmarshalAuthorization(json);
|
||||
|
@ -350,49 +348,23 @@ public class Registration extends AcmeResource {
|
|||
* @param conn
|
||||
* {@link Connection} with headers to be evaluated
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private void unmarshal(Map<String, Object> json, Connection conn) {
|
||||
if (json.containsKey("agreement")) {
|
||||
try {
|
||||
this.agreement = new URI((String) json.get("agreement"));
|
||||
} catch (ClassCastException | URISyntaxException ex) {
|
||||
throw new AcmeProtocolException("Illegal agreement URI", ex);
|
||||
}
|
||||
private void unmarshal(JSON json, Connection conn) {
|
||||
if (json.contains("agreement")) {
|
||||
this.agreement = json.get("agreement").asURI();
|
||||
}
|
||||
|
||||
if (json.containsKey("contact")) {
|
||||
if (json.contains("contact")) {
|
||||
contacts.clear();
|
||||
for (Object c : (Collection<Object>) json.get("contact")) {
|
||||
try {
|
||||
contacts.add(new URI((String) c));
|
||||
} catch (ClassCastException | URISyntaxException ex) {
|
||||
throw new AcmeProtocolException("Illegal contact URI", ex);
|
||||
}
|
||||
for (JSON.Value v : json.get("contact").asArray()) {
|
||||
contacts.add(v.asURI());
|
||||
}
|
||||
}
|
||||
|
||||
if (json.containsKey("authorizations")) {
|
||||
try {
|
||||
this.authorizations = new URI((String) json.get("authorizations"));
|
||||
} catch (ClassCastException | URISyntaxException ex) {
|
||||
throw new AcmeProtocolException("Illegal authorizations URI", ex);
|
||||
}
|
||||
} else {
|
||||
this.authorizations = null;
|
||||
}
|
||||
this.authorizations = json.get("authorizations").asURI();
|
||||
this.certificates = json.get("certificates").asURI();
|
||||
|
||||
if (json.containsKey("certificates")) {
|
||||
try {
|
||||
this.certificates = new URI((String) json.get("certificates"));
|
||||
} catch (ClassCastException | URISyntaxException ex) {
|
||||
throw new AcmeProtocolException("Illegal certificates URI", ex);
|
||||
}
|
||||
} else {
|
||||
this.certificates = null;
|
||||
}
|
||||
|
||||
if (json.containsKey("status")) {
|
||||
this.status = Status.parse((String) json.get("status"));
|
||||
if (json.contains("status")) {
|
||||
this.status = Status.parse(json.get("status").asString());
|
||||
}
|
||||
|
||||
URI location = conn.getLocation();
|
||||
|
@ -490,7 +462,7 @@ public class Registration extends AcmeResource {
|
|||
conn.sendSignedRequest(getLocation(), claims, getSession());
|
||||
conn.accept(HttpURLConnection.HTTP_ACCEPTED);
|
||||
|
||||
Map<String, Object> json = conn.readJsonResponse();
|
||||
JSON json = conn.readJsonResponse();
|
||||
unmarshal(json, conn);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
package org.shredzone.acme4j;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.security.KeyPair;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
|
@ -29,8 +28,8 @@ import org.shredzone.acme4j.challenge.Challenge;
|
|||
import org.shredzone.acme4j.challenge.TokenChallenge;
|
||||
import org.shredzone.acme4j.connector.Resource;
|
||||
import org.shredzone.acme4j.exception.AcmeException;
|
||||
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
||||
import org.shredzone.acme4j.provider.AcmeProvider;
|
||||
import org.shredzone.acme4j.util.JSON;
|
||||
|
||||
/**
|
||||
* A session stores the ACME server URI and the account's key pair. It also tracks
|
||||
|
@ -46,7 +45,7 @@ public class Session {
|
|||
private KeyPair keyPair;
|
||||
private AcmeProvider provider;
|
||||
private byte[] nonce;
|
||||
private Map<String, Object> directoryMap;
|
||||
private JSON directoryJson;
|
||||
private Metadata metadata;
|
||||
private Locale locale = Locale.getDefault();
|
||||
protected Date directoryCacheExpiry;
|
||||
|
@ -162,17 +161,14 @@ public class Session {
|
|||
* Challenge JSON data
|
||||
* @return {@link Challenge} instance
|
||||
*/
|
||||
public Challenge createChallenge(Map<String, Object> data) {
|
||||
public Challenge createChallenge(JSON data) {
|
||||
Objects.requireNonNull(data, "data");
|
||||
|
||||
String type = (String) data.get("type");
|
||||
if (type == null || type.isEmpty()) {
|
||||
throw new IllegalArgumentException("type must not be empty or null");
|
||||
}
|
||||
String type = data.get("type").required().asString();
|
||||
|
||||
Challenge challenge = provider().createChallenge(this, type);
|
||||
if (challenge == null) {
|
||||
if (data.containsKey("token")) {
|
||||
if (data.contains("token")) {
|
||||
challenge = new TokenChallenge(this);
|
||||
} else {
|
||||
challenge = new Challenge(this);
|
||||
|
@ -210,30 +206,25 @@ public class Session {
|
|||
* Reads the provider's directory, then rebuild the resource map. The response is
|
||||
* cached.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private void readDirectory() throws AcmeException {
|
||||
synchronized (this) {
|
||||
Date now = new Date();
|
||||
if (directoryMap == null || !directoryCacheExpiry.after(now)) {
|
||||
directoryMap = provider().directory(this, getServerUri());
|
||||
if (directoryJson == null || !directoryCacheExpiry.after(now)) {
|
||||
directoryJson = provider().directory(this, getServerUri());
|
||||
directoryCacheExpiry = new Date(now.getTime() + 60 * 60 * 1000L);
|
||||
|
||||
Object meta = directoryMap.get("meta");
|
||||
if (meta != null && meta instanceof Map) {
|
||||
metadata = new Metadata((Map<String, Object>) meta);
|
||||
JSON meta = directoryJson.get("meta").asObject();
|
||||
if (meta != null) {
|
||||
metadata = new Metadata(meta);
|
||||
} else {
|
||||
metadata = new Metadata();
|
||||
metadata = new Metadata(JSON.empty());
|
||||
}
|
||||
|
||||
resourceMap.clear();
|
||||
for (Map.Entry<String, Object> entry : directoryMap.entrySet()) {
|
||||
Resource res = Resource.parse(entry.getKey());
|
||||
if (res != null) {
|
||||
try {
|
||||
resourceMap.put(res, new URI(entry.getValue().toString()));
|
||||
} catch (URISyntaxException ex) {
|
||||
throw new AcmeProtocolException("Illegal URI for resource " + res, ex);
|
||||
}
|
||||
for (Resource res : Resource.values()) {
|
||||
URI uri = directoryJson.get(res.path()).asURI();
|
||||
if (uri != null) {
|
||||
resourceMap.put(res, uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,22 +13,11 @@
|
|||
*/
|
||||
package org.shredzone.acme4j.challenge;
|
||||
|
||||
import static org.shredzone.acme4j.util.AcmeUtils.parseTimestamp;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.jose4j.json.JsonUtil;
|
||||
import org.jose4j.lang.JoseException;
|
||||
import org.shredzone.acme4j.AcmeResource;
|
||||
import org.shredzone.acme4j.Session;
|
||||
import org.shredzone.acme4j.Status;
|
||||
|
@ -36,6 +25,7 @@ import org.shredzone.acme4j.connector.Connection;
|
|||
import org.shredzone.acme4j.exception.AcmeException;
|
||||
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
||||
import org.shredzone.acme4j.exception.AcmeRetryAfterException;
|
||||
import org.shredzone.acme4j.util.JSON;
|
||||
import org.shredzone.acme4j.util.JSONBuilder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -58,7 +48,7 @@ public class Challenge extends AcmeResource {
|
|||
protected static final String KEY_URI = "uri";
|
||||
protected static final String KEY_VALIDATED = "validated";
|
||||
|
||||
private transient Map<String, Object> data = new HashMap<>();
|
||||
private JSON data = JSON.empty();
|
||||
|
||||
/**
|
||||
* Returns a {@link Challenge} object of an existing challenge.
|
||||
|
@ -79,8 +69,8 @@ public class Challenge extends AcmeResource {
|
|||
conn.sendRequest(location, session);
|
||||
conn.accept(HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_ACCEPTED);
|
||||
|
||||
Map<String, Object> json = conn.readJsonResponse();
|
||||
if (!(json.containsKey("type"))) {
|
||||
JSON json = conn.readJsonResponse();
|
||||
if (!(json.contains("type"))) {
|
||||
throw new IllegalArgumentException("Provided URI is not a challenge URI");
|
||||
}
|
||||
|
||||
|
@ -102,14 +92,14 @@ public class Challenge extends AcmeResource {
|
|||
* Returns the challenge type by name (e.g. "http-01").
|
||||
*/
|
||||
public String getType() {
|
||||
return get(KEY_TYPE);
|
||||
return data.get(KEY_TYPE).asString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current status of the challenge.
|
||||
*/
|
||||
public Status getStatus() {
|
||||
return Status.parse((String) get(KEY_STATUS), Status.PENDING);
|
||||
return Status.parse(data.get(KEY_STATUS).asString(), Status.PENDING);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -117,24 +107,21 @@ public class Challenge extends AcmeResource {
|
|||
*/
|
||||
@Override
|
||||
public URI getLocation() {
|
||||
String uri = get(KEY_URI);
|
||||
if (uri == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return URI.create(uri);
|
||||
return data.get(KEY_URI).asURI();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the validation date, if returned by the server.
|
||||
*/
|
||||
public Date getValidated() {
|
||||
String valStr = get(KEY_VALIDATED);
|
||||
if (valStr != null) {
|
||||
return parseTimestamp(valStr);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return data.get(KEY_VALIDATED).asDate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the JSON representation of the challenge data.
|
||||
*/
|
||||
protected JSON getJSON() {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -161,11 +148,11 @@ public class Challenge extends AcmeResource {
|
|||
/**
|
||||
* Sets the challenge state to the given JSON map.
|
||||
*
|
||||
* @param map
|
||||
* JSON map containing the challenge data
|
||||
* @param json
|
||||
* JSON containing the challenge data
|
||||
*/
|
||||
public void unmarshall(Map<String, Object> map) {
|
||||
String type = (String) map.get(KEY_TYPE);
|
||||
public void unmarshall(JSON json) {
|
||||
String type = json.get(KEY_TYPE).asString();
|
||||
if (type == null) {
|
||||
throw new IllegalArgumentException("map does not contain a type");
|
||||
}
|
||||
|
@ -173,39 +160,10 @@ public class Challenge extends AcmeResource {
|
|||
throw new AcmeProtocolException("wrong type: " + type);
|
||||
}
|
||||
|
||||
data.clear();
|
||||
data.putAll(map);
|
||||
data = json;
|
||||
authorize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a value from the challenge state.
|
||||
*
|
||||
* @param key
|
||||
* Key
|
||||
* @return Value, or {@code null} if not set
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T> T get(String key) {
|
||||
return (T) data.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an {@link URL} value from the challenge state.
|
||||
*
|
||||
* @param key
|
||||
* Key
|
||||
* @return Value, or {@code null} if not set
|
||||
*/
|
||||
protected URL getUrl(String key) {
|
||||
try {
|
||||
String value = get(key);
|
||||
return value != null ? new URL(value) : null;
|
||||
} catch (MalformedURLException ex) {
|
||||
throw new AcmeProtocolException(key + ": invalid URL", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback that is invoked when the challenge is supposed to compute its
|
||||
* authorization data.
|
||||
|
@ -260,24 +218,4 @@ public class Challenge extends AcmeResource {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize the data map in JSON.
|
||||
*/
|
||||
private void writeObject(ObjectOutputStream out) throws IOException {
|
||||
out.writeUTF(JsonUtil.toJson(data));
|
||||
out.defaultWriteObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize the JSON representation of the data map.
|
||||
*/
|
||||
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
try {
|
||||
data = new HashMap<>(JsonUtil.parseJson(in.readUTF()));
|
||||
in.defaultReadObject();
|
||||
} catch (JoseException ex) {
|
||||
throw new AcmeProtocolException("Cannot deserialize", ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ public class OutOfBand01Challenge extends Challenge {
|
|||
* challenge.
|
||||
*/
|
||||
public URL getValidationUrl() {
|
||||
return getUrl("href");
|
||||
return getJSON().get("href").asURL();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -56,11 +56,7 @@ public class TokenChallenge extends Challenge {
|
|||
* Gets the token.
|
||||
*/
|
||||
protected String getToken() {
|
||||
String token = get(KEY_TOKEN);
|
||||
if (token == null) {
|
||||
throw new AcmeProtocolException("Challenge token required, but not set");
|
||||
}
|
||||
return token;
|
||||
return getJSON().get(KEY_TOKEN).required().asString();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,11 +17,11 @@ import java.net.URI;
|
|||
import java.security.cert.X509Certificate;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
import org.shredzone.acme4j.Session;
|
||||
import org.shredzone.acme4j.exception.AcmeException;
|
||||
import org.shredzone.acme4j.util.JSONBuilder;
|
||||
import org.shredzone.acme4j.util.JSON;
|
||||
|
||||
/**
|
||||
* Connects to the ACME server and offers different methods for invoking the API.
|
||||
|
@ -63,9 +63,9 @@ public interface Connection extends AutoCloseable {
|
|||
/**
|
||||
* Reads a server response as JSON data.
|
||||
*
|
||||
* @return Map containing the parsed JSON data
|
||||
* @return The JSON response
|
||||
*/
|
||||
Map<String, Object> readJsonResponse() throws AcmeException;
|
||||
JSON readJsonResponse() throws AcmeException;
|
||||
|
||||
/**
|
||||
* Reads a certificate.
|
||||
|
|
|
@ -15,10 +15,8 @@ package org.shredzone.acme4j.connector;
|
|||
|
||||
import static org.shredzone.acme4j.util.AcmeUtils.keyAlgorithm;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
|
@ -39,7 +37,6 @@ import java.util.regex.Matcher;
|
|||
import java.util.regex.Pattern;
|
||||
|
||||
import org.jose4j.base64url.Base64Url;
|
||||
import org.jose4j.json.JsonUtil;
|
||||
import org.jose4j.jwk.PublicJsonWebKey;
|
||||
import org.jose4j.jws.JsonWebSignature;
|
||||
import org.jose4j.lang.JoseException;
|
||||
|
@ -52,6 +49,7 @@ import org.shredzone.acme4j.exception.AcmeProtocolException;
|
|||
import org.shredzone.acme4j.exception.AcmeRateLimitExceededException;
|
||||
import org.shredzone.acme4j.exception.AcmeServerException;
|
||||
import org.shredzone.acme4j.exception.AcmeUnauthorizedException;
|
||||
import org.shredzone.acme4j.util.JSON;
|
||||
import org.shredzone.acme4j.util.JSONBuilder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -177,15 +175,15 @@ public class DefaultConnection implements Connection {
|
|||
throw new AcmeException("HTTP " + rc + ": " + conn.getResponseMessage());
|
||||
}
|
||||
|
||||
Map<String, Object> map = readJsonResponse();
|
||||
throw createAcmeException(rc, map);
|
||||
JSON json = readJsonResponse();
|
||||
throw createAcmeException(rc, json);
|
||||
} catch (IOException ex) {
|
||||
throw new AcmeNetworkException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> readJsonResponse() throws AcmeException {
|
||||
public JSON readJsonResponse() throws AcmeException {
|
||||
assertConnectionIsOpen();
|
||||
|
||||
String contentType = conn.getHeaderField("Content-Type");
|
||||
|
@ -194,41 +192,23 @@ public class DefaultConnection implements Connection {
|
|||
throw new AcmeProtocolException("Unexpected content type: " + contentType);
|
||||
}
|
||||
|
||||
Map<String, Object> result = null;
|
||||
JSON result = null;
|
||||
|
||||
String response = "";
|
||||
try {
|
||||
InputStream in =
|
||||
conn.getResponseCode() < 400 ? conn.getInputStream() : conn.getErrorStream();
|
||||
if (in != null) {
|
||||
response = readStream(in);
|
||||
result = JsonUtil.parseJson(response);
|
||||
result = JSON.parse(in);
|
||||
LOG.debug("Result JSON: {}", response);
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
throw new AcmeNetworkException(ex);
|
||||
} catch (JoseException ex) {
|
||||
throw new AcmeProtocolException("Failed to parse response: " + response, ex);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private String readStream(InputStream in) throws IOException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(in, "utf-8"))) {
|
||||
String line = reader.readLine();
|
||||
|
||||
while (line != null) {
|
||||
sb.append(line.trim());
|
||||
line = reader.readLine();
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public X509Certificate readCertificate() throws AcmeException {
|
||||
assertConnectionIsOpen();
|
||||
|
@ -351,9 +331,9 @@ public class DefaultConnection implements Connection {
|
|||
* {@link AcmeServerException} will be thrown. Otherwise a generic
|
||||
* {@link AcmeException} is thrown.
|
||||
*/
|
||||
private AcmeException createAcmeException(int rc, Map<String, Object> map) {
|
||||
String type = (String) map.get("type");
|
||||
String detail = (String) map.get("detail");
|
||||
private AcmeException createAcmeException(int rc, JSON json) {
|
||||
String type = json.get("type").asString();
|
||||
String detail = json.get("detail").asString();
|
||||
|
||||
if (detail == null) {
|
||||
detail = "general problem";
|
||||
|
@ -374,7 +354,7 @@ public class DefaultConnection implements Connection {
|
|||
|
||||
case ACME_ERROR_PREFIX + "agreementRequired":
|
||||
case ACME_ERROR_PREFIX_DEPRECATED + "agreementRequired":
|
||||
String instance = (String) map.get("instance");
|
||||
String instance = json.get("instance").asString();
|
||||
return new AcmeAgreementRequiredException(
|
||||
type, detail, getLink("terms-of-service"),
|
||||
instance != null ? resolveRelative(instance) : null);
|
||||
|
|
|
@ -15,18 +15,16 @@ package org.shredzone.acme4j.connector;
|
|||
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Collection;
|
||||
import java.util.Deque;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import org.shredzone.acme4j.AcmeResource;
|
||||
import org.shredzone.acme4j.Session;
|
||||
import org.shredzone.acme4j.exception.AcmeException;
|
||||
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
||||
import org.shredzone.acme4j.util.JSON;
|
||||
|
||||
/**
|
||||
* An {@link Iterator} that fetches a batch of URIs from the ACME server, and
|
||||
|
@ -147,7 +145,7 @@ public abstract class ResourceIterator<T extends AcmeResource> implements Iterat
|
|||
conn.sendRequest(nextUri, session);
|
||||
conn.accept(HttpURLConnection.HTTP_OK);
|
||||
|
||||
Map<String, Object> json = conn.readJsonResponse();
|
||||
JSON json = conn.readJsonResponse();
|
||||
fillUriList(json);
|
||||
|
||||
nextUri = conn.getLink("next");
|
||||
|
@ -160,21 +158,13 @@ public abstract class ResourceIterator<T extends AcmeResource> implements Iterat
|
|||
* @param json
|
||||
* JSON map to read from
|
||||
*/
|
||||
private void fillUriList(Map<String, Object> json) {
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
Collection<String> array = (Collection<String>) json.get(field);
|
||||
if (array == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (String uri : array) {
|
||||
uriList.add(new URI(uri));
|
||||
}
|
||||
} catch (ClassCastException ex) {
|
||||
throw new AcmeProtocolException("Expected an array", ex);
|
||||
} catch (URISyntaxException ex) {
|
||||
throw new AcmeProtocolException("Invalid URI", ex);
|
||||
private void fillUriList(JSON json) {
|
||||
JSON.Array array = json.get(field).asArray();
|
||||
if (array == null) {
|
||||
return;
|
||||
}
|
||||
for (JSON.Value v : array) {
|
||||
uriList.add(v.asURI());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@ package org.shredzone.acme4j.provider;
|
|||
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.shredzone.acme4j.Session;
|
||||
|
@ -28,6 +27,7 @@ import org.shredzone.acme4j.connector.Connection;
|
|||
import org.shredzone.acme4j.connector.DefaultConnection;
|
||||
import org.shredzone.acme4j.connector.HttpConnector;
|
||||
import org.shredzone.acme4j.exception.AcmeException;
|
||||
import org.shredzone.acme4j.util.JSON;
|
||||
|
||||
/**
|
||||
* Abstract implementation of {@link AcmeProvider}. It consists of a challenge
|
||||
|
@ -44,7 +44,7 @@ public abstract class AbstractAcmeProvider implements AcmeProvider {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> directory(Session session, URI serverUri) throws AcmeException {
|
||||
public JSON directory(Session session, URI serverUri) throws AcmeException {
|
||||
try (Connection conn = connect()) {
|
||||
conn.sendRequest(resolve(serverUri), session);
|
||||
conn.accept(HttpURLConnection.HTTP_OK);
|
||||
|
|
|
@ -14,13 +14,13 @@
|
|||
package org.shredzone.acme4j.provider;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
import org.shredzone.acme4j.Session;
|
||||
import org.shredzone.acme4j.challenge.Challenge;
|
||||
import org.shredzone.acme4j.connector.Connection;
|
||||
import org.shredzone.acme4j.exception.AcmeException;
|
||||
import org.shredzone.acme4j.util.JSON;
|
||||
|
||||
/**
|
||||
* An {@link AcmeProvider} provides methods to be used for communicating with the ACME
|
||||
|
@ -69,9 +69,9 @@ public interface AcmeProvider {
|
|||
* {@link Session} to be used
|
||||
* @param serverUri
|
||||
* Server {@link URI}
|
||||
* @return Map of directory data
|
||||
* @return Directory data, as JSON object
|
||||
*/
|
||||
Map<String, Object> directory(Session session, URI serverUri) throws AcmeException;
|
||||
JSON directory(Session session, URI serverUri) throws AcmeException;
|
||||
|
||||
/**
|
||||
* Creates a {@link Challenge} instance for the given challenge type.
|
||||
|
|
|
@ -0,0 +1,386 @@
|
|||
/*
|
||||
* acme4j - Java ACME client
|
||||
*
|
||||
* Copyright (C) 2016 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.util;
|
||||
|
||||
import static org.shredzone.acme4j.util.AcmeUtils.parseTimestamp;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jose4j.json.JsonUtil;
|
||||
import org.jose4j.lang.JoseException;
|
||||
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
||||
|
||||
/**
|
||||
* A model containing a JSON result. The content is immutable.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public final class JSON implements Serializable {
|
||||
private static final long serialVersionUID = 3091273044605709204L;
|
||||
|
||||
private static final JSON EMPTY_JSON = new JSON(new HashMap<String, Object>());
|
||||
|
||||
private final String path;
|
||||
private Map<String, Object> data;
|
||||
|
||||
/**
|
||||
* Creates a new {@link JSON} root object.
|
||||
*
|
||||
* @param data
|
||||
* {@link Map} containing the parsed JSON data
|
||||
*/
|
||||
private JSON(Map<String, Object> data) {
|
||||
this("", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link JSON} branch object.
|
||||
*
|
||||
* @param path
|
||||
* Path leading to this branch.
|
||||
* @param data
|
||||
* {@link Map} containing the parsed JSON data
|
||||
*/
|
||||
private JSON(String path, Map<String, Object> data) {
|
||||
this.path = path;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses JSON from an {@link InputStream}.
|
||||
*
|
||||
* @param in
|
||||
* {@link InputStream} to read from. Will be closed after use.
|
||||
* @return {@link JSON} of the read content.
|
||||
*/
|
||||
public static JSON parse(InputStream in) throws IOException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(in, "utf-8"))) {
|
||||
String line = reader.readLine();
|
||||
|
||||
while (line != null) {
|
||||
sb.append(line.trim());
|
||||
line = reader.readLine();
|
||||
}
|
||||
}
|
||||
|
||||
return parse(sb.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses JSON from a String.
|
||||
*
|
||||
* @param json
|
||||
* JSON string
|
||||
* @return {@link JSON} of the read content.
|
||||
*/
|
||||
public static JSON parse(String json) {
|
||||
try {
|
||||
return new JSON(JsonUtil.parseJson(json));
|
||||
} catch (JoseException ex) {
|
||||
throw new AcmeProtocolException("Bad JSON: " + json, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link JSON} of an empty document.
|
||||
*/
|
||||
public static JSON empty() {
|
||||
return EMPTY_JSON;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Set} of all keys of this object.
|
||||
*/
|
||||
public Set<String> keySet() {
|
||||
return Collections.unmodifiableSet(data.keySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this object contains the given key.
|
||||
*
|
||||
* @param key
|
||||
* Name of the key to check
|
||||
* @return {@code true} if the key is present
|
||||
*/
|
||||
public boolean contains(String key) {
|
||||
return data.containsKey(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Value} of the given key.
|
||||
*
|
||||
* @param key
|
||||
* Key to read
|
||||
* @return {@link Value} of the key
|
||||
*/
|
||||
public Value get(String key) {
|
||||
return new Value(
|
||||
path.isEmpty() ? key : path + '.' + key,
|
||||
data.get(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the content as JSON string.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return JsonUtil.toJson(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize the data map in JSON.
|
||||
*/
|
||||
private void writeObject(ObjectOutputStream out) throws IOException {
|
||||
out.writeUTF(JsonUtil.toJson(data));
|
||||
out.defaultWriteObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize the JSON representation of the data map.
|
||||
*/
|
||||
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
try {
|
||||
data = new HashMap<>(JsonUtil.parseJson(in.readUTF()));
|
||||
in.defaultReadObject();
|
||||
} catch (JoseException ex) {
|
||||
throw new AcmeProtocolException("Cannot deserialize", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a JSON array.
|
||||
*/
|
||||
public static final class Array implements Iterable<Value> {
|
||||
private final String path;
|
||||
private final List<Object> data;
|
||||
|
||||
/**
|
||||
* Creates a new {@link Array} object.
|
||||
*
|
||||
* @param path
|
||||
* JSON path to this array.
|
||||
* @param data
|
||||
* Array data
|
||||
*/
|
||||
private Array(String path, List<Object> data) {
|
||||
this.path = path;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the array size.
|
||||
*/
|
||||
public int size() {
|
||||
return data.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link Value} at the given index.
|
||||
*
|
||||
* @param index
|
||||
* Array index to read from
|
||||
* @return {@link Value} at this index
|
||||
*/
|
||||
public Value get(int index) {
|
||||
return new Value(path + '[' + index + ']', data.get(index));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Iterator} that iterates over the array {@link Value}.
|
||||
*/
|
||||
@Override
|
||||
public Iterator<Value> iterator() {
|
||||
return new ValueIterator(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A single JSON value. This instance also covers {@code null} values.
|
||||
*/
|
||||
public static final class Value {
|
||||
private final String path;
|
||||
private final Object val;
|
||||
|
||||
/**
|
||||
* Creates a new {@link Value}.
|
||||
*
|
||||
* @param path
|
||||
* JSON path to this value
|
||||
* @param val
|
||||
* Value, may be {@code null}
|
||||
*/
|
||||
private Value(String path, Object val) {
|
||||
this.path = path;
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the value is present. An {@link AcmeProtocolException} is thrown
|
||||
* if the value is {@code null}.
|
||||
*/
|
||||
public Value required() {
|
||||
if (val == null) {
|
||||
throw new AcmeProtocolException(path + ": required, but not set");
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value as {@link String}. May be {@code null}.
|
||||
*/
|
||||
public String asString() {
|
||||
return val != null ? val.toString() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value as {@link JSON} object. May be {@code null}.
|
||||
*/
|
||||
public JSON asObject() {
|
||||
if (val == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new JSON(path, (Map<String, Object>) val);
|
||||
} catch (ClassCastException ex) {
|
||||
throw new AcmeProtocolException(path + ": expected an object", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value as JSON {@link Array}. May be {@code null}.
|
||||
*/
|
||||
public Array asArray() {
|
||||
if (val == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new Array(path, (List<Object>) val);
|
||||
} catch (ClassCastException ex) {
|
||||
throw new AcmeProtocolException(path + ": expected an array", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value as int.
|
||||
*/
|
||||
public int asInt() {
|
||||
required();
|
||||
|
||||
try {
|
||||
return ((Number) val).intValue();
|
||||
} catch (ClassCastException ex) {
|
||||
throw new AcmeProtocolException(path + ": bad number " + val, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value as {@link URI}. May be {@code null}.
|
||||
*/
|
||||
public URI asURI() {
|
||||
if (val == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new URI(val.toString());
|
||||
} catch (URISyntaxException ex) {
|
||||
throw new AcmeProtocolException(path + ": bad URI " + val, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value as {@link URL}. May be {@code null}.
|
||||
*/
|
||||
public URL asURL() {
|
||||
if (val == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new URL(val.toString());
|
||||
} catch (MalformedURLException ex) {
|
||||
throw new AcmeProtocolException(path + ": bad URL " + val, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value as {@link Date}. May be {@code null}. The returned
|
||||
* {@link Date} object is not shared, changes are not reflected in the JSON
|
||||
* object.
|
||||
*/
|
||||
public Date asDate() {
|
||||
if (val == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return parseTimestamp(val.toString());
|
||||
} catch (IllegalArgumentException ex) {
|
||||
throw new AcmeProtocolException(path + ": bad date " + val, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An {@link Iterator} over array {@link Value}.
|
||||
*/
|
||||
private static class ValueIterator implements Iterator<Value> {
|
||||
private final Array array;
|
||||
private int index = 0;
|
||||
|
||||
public ValueIterator(Array array) {
|
||||
this.array = array;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return index < array.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value next() {
|
||||
if (!hasNext()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
return array.get(index++);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -175,6 +175,13 @@ public class JSONBuilder {
|
|||
return Collections.unmodifiableMap(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link JSON} representation of the current state.
|
||||
*/
|
||||
public JSON toJSON() {
|
||||
return JSON.parse(toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a JSON string representation of the current state.
|
||||
*/
|
||||
|
|
|
@ -23,7 +23,6 @@ import java.net.HttpURLConnection;
|
|||
import java.net.URI;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.junit.Test;
|
||||
|
@ -34,6 +33,7 @@ import org.shredzone.acme4j.challenge.TlsSni02Challenge;
|
|||
import org.shredzone.acme4j.exception.AcmeException;
|
||||
import org.shredzone.acme4j.exception.AcmeRetryAfterException;
|
||||
import org.shredzone.acme4j.provider.TestableConnectionProvider;
|
||||
import org.shredzone.acme4j.util.JSON;
|
||||
import org.shredzone.acme4j.util.JSONBuilder;
|
||||
|
||||
/**
|
||||
|
@ -132,8 +132,8 @@ public class AuthorizationTest {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> readJsonResponse() {
|
||||
return getJsonAsMap("updateAuthorizationResponse");
|
||||
public JSON readJsonResponse() {
|
||||
return getJsonAsObject("updateAuthorizationResponse");
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -186,8 +186,8 @@ public class AuthorizationTest {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> readJsonResponse() {
|
||||
return getJsonAsMap("updateAuthorizationResponse");
|
||||
public JSON readJsonResponse() {
|
||||
return getJsonAsObject("updateAuthorizationResponse");
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -234,8 +234,8 @@ public class AuthorizationTest {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> readJsonResponse() {
|
||||
return getJsonAsMap("updateAuthorizationResponse");
|
||||
public JSON readJsonResponse() {
|
||||
return getJsonAsObject("updateAuthorizationResponse");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -285,9 +285,9 @@ public class AuthorizationTest {
|
|||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||
@Override
|
||||
public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) {
|
||||
Map<String, Object> claimMap = claims.toMap();
|
||||
assertThat(claimMap.get("resource"), is((Object) "authz"));
|
||||
assertThat(claimMap.get("status"), is((Object) "deactivated"));
|
||||
JSON json = claims.toJSON();
|
||||
assertThat(json.get("resource").asString(), is("authz"));
|
||||
assertThat(json.get("status").asString(), is("deactivated"));
|
||||
assertThat(uri, is(locationUri));
|
||||
assertThat(session, is(notNullValue()));
|
||||
}
|
||||
|
@ -318,7 +318,7 @@ public class AuthorizationTest {
|
|||
provider.putTestChallenge(TlsSni02Challenge.TYPE, new TlsSni02Challenge(session));
|
||||
|
||||
Authorization authorization = new Authorization(session, locationUri);
|
||||
authorization.unmarshalAuthorization(getJsonAsMap("authorizationChallenges"));
|
||||
authorization.unmarshalAuthorization(getJsonAsObject("authorizationChallenges"));
|
||||
return authorization;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,11 +23,8 @@ import java.net.HttpURLConnection;
|
|||
import java.net.URI;
|
||||
import java.security.KeyPair;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
|
@ -43,6 +40,7 @@ import org.shredzone.acme4j.connector.Resource;
|
|||
import org.shredzone.acme4j.exception.AcmeException;
|
||||
import org.shredzone.acme4j.provider.AcmeProvider;
|
||||
import org.shredzone.acme4j.provider.TestableConnectionProvider;
|
||||
import org.shredzone.acme4j.util.JSON;
|
||||
import org.shredzone.acme4j.util.JSONBuilder;
|
||||
import org.shredzone.acme4j.util.TestUtils;
|
||||
|
||||
|
@ -62,7 +60,7 @@ public class RegistrationTest {
|
|||
@Test
|
||||
public void testUpdateRegistration() throws AcmeException, IOException {
|
||||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||
private Map<String, Object> jsonResponse;
|
||||
private JSON jsonResponse;
|
||||
private Integer response;
|
||||
|
||||
@Override
|
||||
|
@ -70,24 +68,24 @@ public class RegistrationTest {
|
|||
assertThat(uri, is(locationUri));
|
||||
assertThat(claims.toString(), sameJSONAs(getJson("updateRegistration")));
|
||||
assertThat(session, is(notNullValue()));
|
||||
jsonResponse = getJsonAsMap("updateRegistrationResponse");
|
||||
jsonResponse = getJsonAsObject("updateRegistrationResponse");
|
||||
response = HttpURLConnection.HTTP_ACCEPTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendRequest(URI uri, Session session) {
|
||||
if (URI.create("https://example.com/acme/reg/1/authz").equals(uri)) {
|
||||
jsonResponse = new HashMap<>();
|
||||
jsonResponse.put("authorizations",
|
||||
Arrays.asList("https://example.com/acme/auth/1"));
|
||||
jsonResponse = new JSONBuilder()
|
||||
.array("authorizations", "https://example.com/acme/auth/1")
|
||||
.toJSON();
|
||||
response = HttpURLConnection.HTTP_OK;
|
||||
return;
|
||||
}
|
||||
|
||||
if (URI.create("https://example.com/acme/reg/1/cert").equals(uri)) {
|
||||
jsonResponse = new HashMap<>();
|
||||
jsonResponse.put("certificates",
|
||||
Arrays.asList("https://example.com/acme/cert/1"));
|
||||
jsonResponse = new JSONBuilder()
|
||||
.array("certificates", "https://example.com/acme/cert/1")
|
||||
.toJSON();
|
||||
response = HttpURLConnection.HTTP_OK;
|
||||
return;
|
||||
}
|
||||
|
@ -102,7 +100,7 @@ public class RegistrationTest {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> readJsonResponse() {
|
||||
public JSON readJsonResponse() {
|
||||
return jsonResponse;
|
||||
}
|
||||
|
||||
|
@ -167,8 +165,8 @@ public class RegistrationTest {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> readJsonResponse() {
|
||||
return getJsonAsMap("updateRegistrationResponse");
|
||||
public JSON readJsonResponse() {
|
||||
return getJsonAsObject("updateRegistrationResponse");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -221,8 +219,8 @@ public class RegistrationTest {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> readJsonResponse() {
|
||||
return getJsonAsMap("newAuthorizationResponse");
|
||||
public JSON readJsonResponse() {
|
||||
return getJsonAsObject("newAuthorizationResponse");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -417,12 +415,12 @@ public class RegistrationTest {
|
|||
assertThat(session, is(notNullValue()));
|
||||
assertThat(session.getKeyPair(), is(sameInstance(oldKeyPair)));
|
||||
|
||||
Map<String, Object> json = payload.toMap();
|
||||
assertThat((String) json.get("resource"), is("key-change")); // Required by Let's Encrypt
|
||||
JSON json = payload.toJSON();
|
||||
assertThat(json.get("resource").asString(), is("key-change")); // Required by Let's Encrypt
|
||||
|
||||
String encodedHeader = (String) json.get("protected");
|
||||
String encodedSignature = (String) json.get("signature");
|
||||
String encodedPayload = (String) json.get("payload");
|
||||
String encodedHeader = json.get("protected").asString();
|
||||
String encodedSignature = json.get("signature").asString();
|
||||
String encodedPayload = json.get("payload").asString();
|
||||
|
||||
String serialized = CompactSerializer.serialize(encodedHeader, encodedPayload, encodedSignature);
|
||||
JsonWebSignature jws = new JsonWebSignature();
|
||||
|
@ -497,9 +495,9 @@ public class RegistrationTest {
|
|||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||
@Override
|
||||
public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) {
|
||||
Map<String, Object> claimMap = claims.toMap();
|
||||
assertThat(claimMap.get("resource"), is((Object) "reg"));
|
||||
assertThat(claimMap.get("status"), is((Object) "deactivated"));
|
||||
JSON json = claims.toJSON();
|
||||
assertThat(json.get("resource").asString(), is("reg"));
|
||||
assertThat(json.get("status").asString(), is("deactivated"));
|
||||
assertThat(uri, is(locationUri));
|
||||
assertThat(session, is(notNullValue()));
|
||||
}
|
||||
|
@ -540,8 +538,8 @@ public class RegistrationTest {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> readJsonResponse() {
|
||||
return getJsonAsMap("modifyRegistrationResponse");
|
||||
public JSON readJsonResponse() {
|
||||
return getJsonAsObject("modifyRegistrationResponse");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -16,12 +16,12 @@ package org.shredzone.acme4j;
|
|||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.shredzone.acme4j.util.TestUtils.getJsonAsObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.security.KeyPair;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
|
@ -30,6 +30,7 @@ import org.shredzone.acme4j.challenge.Http01Challenge;
|
|||
import org.shredzone.acme4j.connector.Resource;
|
||||
import org.shredzone.acme4j.exception.AcmeException;
|
||||
import org.shredzone.acme4j.provider.AcmeProvider;
|
||||
import org.shredzone.acme4j.util.JSON;
|
||||
import org.shredzone.acme4j.util.JSONBuilder;
|
||||
import org.shredzone.acme4j.util.TestUtils;
|
||||
|
||||
|
@ -117,9 +118,9 @@ public class SessionTest {
|
|||
URI serverUri = URI.create(TestUtils.ACME_SERVER_URI);
|
||||
String challengeType = Http01Challenge.TYPE;
|
||||
|
||||
Map<String, Object> data = new JSONBuilder()
|
||||
JSON data = new JSONBuilder()
|
||||
.put("type", challengeType)
|
||||
.toMap();
|
||||
.toJSON();
|
||||
|
||||
Http01Challenge mockChallenge = mock(Http01Challenge.class);
|
||||
final AcmeProvider mockProvider = mock(AcmeProvider.class);
|
||||
|
@ -155,7 +156,7 @@ public class SessionTest {
|
|||
when(mockProvider.directory(
|
||||
ArgumentMatchers.any(Session.class),
|
||||
ArgumentMatchers.eq(serverUri)))
|
||||
.thenReturn(TestUtils.getJsonAsMap("directory"));
|
||||
.thenReturn(getJsonAsObject("directory"));
|
||||
|
||||
Session session = new Session(serverUri, keyPair) {
|
||||
@Override
|
||||
|
@ -193,7 +194,7 @@ public class SessionTest {
|
|||
when(mockProvider.directory(
|
||||
ArgumentMatchers.any(Session.class),
|
||||
ArgumentMatchers.eq(serverUri)))
|
||||
.thenReturn(TestUtils.getJsonAsMap("directoryNoMeta"));
|
||||
.thenReturn(getJsonAsObject("directoryNoMeta"));
|
||||
|
||||
Session session = new Session(serverUri, keyPair) {
|
||||
@Override
|
||||
|
@ -239,10 +240,8 @@ public class SessionTest {
|
|||
assertThat(meta, not(nullValue()));
|
||||
assertThat(meta.getTermsOfService(), is(URI.create("https://example.com/acme/terms")));
|
||||
assertThat(meta.getWebsite(), is(URI.create("https://www.example.com/")));
|
||||
assertThat(meta.getCaaIdentities(), is(arrayContaining("example.com")));
|
||||
assertThat(meta.get("x-test-string"), is("foobar"));
|
||||
assertThat(meta.getUri("x-test-uri"), is(URI.create("https://www.example.org")));
|
||||
assertThat(meta.getStringArray("x-test-array"), is(arrayContaining("foo", "bar", "barfoo")));
|
||||
assertThat(meta.getCaaIdentities(), containsInAnyOrder("example.com"));
|
||||
assertThat(meta.getJSON(), is(notNullValue()));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,20 +19,14 @@ import static org.shredzone.acme4j.util.AcmeUtils.parseTimestamp;
|
|||
import static org.shredzone.acme4j.util.TestUtils.*;
|
||||
import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jose4j.json.JsonUtil;
|
||||
import org.jose4j.lang.JoseException;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
@ -42,6 +36,7 @@ import org.shredzone.acme4j.exception.AcmeException;
|
|||
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
||||
import org.shredzone.acme4j.exception.AcmeRetryAfterException;
|
||||
import org.shredzone.acme4j.provider.TestableConnectionProvider;
|
||||
import org.shredzone.acme4j.util.JSON;
|
||||
import org.shredzone.acme4j.util.JSONBuilder;
|
||||
import org.shredzone.acme4j.util.TestUtils;
|
||||
|
||||
|
@ -77,8 +72,8 @@ public class ChallengeTest {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> readJsonResponse() {
|
||||
return getJsonAsMap("updateHttpChallengeResponse");
|
||||
public JSON readJsonResponse() {
|
||||
return getJsonAsObject("updateHttpChallengeResponse");
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -110,24 +105,17 @@ public class ChallengeTest {
|
|||
assertThat(challenge.getValidated(), is(nullValue()));
|
||||
|
||||
// Unmarshall a challenge JSON
|
||||
challenge.unmarshall(TestUtils.getJsonAsMap("genericChallenge"));
|
||||
challenge.unmarshall(getJsonAsObject("genericChallenge"));
|
||||
|
||||
// Test unmarshalled values
|
||||
assertThat(challenge.getType(), is("generic-01"));
|
||||
assertThat(challenge.getStatus(), is(Status.VALID));
|
||||
assertThat(challenge.getLocation(), is(new URI("http://example.com/challenge/123")));
|
||||
assertThat(challenge.getValidated(), is(parseTimestamp("2015-12-12T17:19:36.336785823Z")));
|
||||
assertThat((String) challenge.get("type"), is("generic-01"));
|
||||
assertThat(challenge.getUrl("uri"), is(new URL("http://example.com/challenge/123")));
|
||||
assertThat(challenge.get("not-present"), is(nullValue()));
|
||||
assertThat(challenge.getUrl("not-present-url"), is(nullValue()));
|
||||
|
||||
try {
|
||||
challenge.getUrl("type");
|
||||
fail("bad URL is not detected");
|
||||
} catch (AcmeProtocolException ex) {
|
||||
// expected
|
||||
}
|
||||
assertThat(challenge.getJSON().get("type").asString(), is("generic-01"));
|
||||
assertThat(challenge.getJSON().get("uri").asURL(), is(new URL("http://example.com/challenge/123")));
|
||||
assertThat(challenge.getJSON().get("not-present").asString(), is(nullValue()));
|
||||
assertThat(challenge.getJSON().get("not-present-url").asURL(), is(nullValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -138,7 +126,7 @@ public class ChallengeTest {
|
|||
String json = TestUtils.getJson("genericChallenge");
|
||||
|
||||
Challenge challenge = new Challenge(session);
|
||||
challenge.unmarshall(JsonUtil.parseJson(json));
|
||||
challenge.unmarshall(JSON.parse(json));
|
||||
|
||||
JSONBuilder cb = new JSONBuilder();
|
||||
challenge.respond(cb);
|
||||
|
@ -152,7 +140,7 @@ public class ChallengeTest {
|
|||
@Test(expected = AcmeProtocolException.class)
|
||||
public void testNotAcceptable() throws URISyntaxException {
|
||||
Http01Challenge challenge = new Http01Challenge(session);
|
||||
challenge.unmarshall(TestUtils.getJsonAsMap("dnsChallenge"));
|
||||
challenge.unmarshall(getJsonAsObject("dnsChallenge"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -176,15 +164,15 @@ public class ChallengeTest {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> readJsonResponse() {
|
||||
return getJsonAsMap("triggerHttpChallengeResponse");
|
||||
public JSON readJsonResponse() {
|
||||
return getJsonAsObject("triggerHttpChallengeResponse");
|
||||
}
|
||||
};
|
||||
|
||||
Session session = provider.createSession();
|
||||
|
||||
Http01Challenge challenge = new Http01Challenge(session);
|
||||
challenge.unmarshall(getJsonAsMap("triggerHttpChallenge"));
|
||||
challenge.unmarshall(getJsonAsObject("triggerHttpChallenge"));
|
||||
|
||||
challenge.trigger();
|
||||
|
||||
|
@ -213,15 +201,15 @@ public class ChallengeTest {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> readJsonResponse() {
|
||||
return getJsonAsMap("updateHttpChallengeResponse");
|
||||
public JSON readJsonResponse() {
|
||||
return getJsonAsObject("updateHttpChallengeResponse");
|
||||
}
|
||||
};
|
||||
|
||||
Session session = provider.createSession();
|
||||
|
||||
Challenge challenge = new Http01Challenge(session);
|
||||
challenge.unmarshall(getJsonAsMap("triggerHttpChallengeResponse"));
|
||||
challenge.unmarshall(getJsonAsObject("triggerHttpChallengeResponse"));
|
||||
|
||||
challenge.update();
|
||||
|
||||
|
@ -252,8 +240,8 @@ public class ChallengeTest {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> readJsonResponse() {
|
||||
return getJsonAsMap("updateHttpChallengeResponse");
|
||||
public JSON readJsonResponse() {
|
||||
return getJsonAsObject("updateHttpChallengeResponse");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -265,7 +253,7 @@ public class ChallengeTest {
|
|||
Session session = provider.createSession();
|
||||
|
||||
Challenge challenge = new Http01Challenge(session);
|
||||
challenge.unmarshall(getJsonAsMap("triggerHttpChallengeResponse"));
|
||||
challenge.unmarshall(getJsonAsObject("triggerHttpChallengeResponse"));
|
||||
|
||||
try {
|
||||
challenge.update();
|
||||
|
@ -319,8 +307,8 @@ public class ChallengeTest {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> readJsonResponse() {
|
||||
return getJsonAsMap("updateRegistrationResponse");
|
||||
public JSON readJsonResponse() {
|
||||
return getJsonAsObject("updateRegistrationResponse");
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -336,39 +324,7 @@ public class ChallengeTest {
|
|||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testBadUnmarshall() {
|
||||
Challenge challenge = new Challenge(session);
|
||||
challenge.unmarshall(TestUtils.getJsonAsMap("updateRegistrationResponse"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that challenge serialization works correctly.
|
||||
*/
|
||||
@Test
|
||||
public void testSerialization() throws IOException, ClassNotFoundException {
|
||||
Http01Challenge originalChallenge = new Http01Challenge(session);
|
||||
originalChallenge.unmarshall(TestUtils.getJsonAsMap("httpChallenge"));
|
||||
|
||||
// Serialize
|
||||
byte[] data;
|
||||
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
|
||||
try (ObjectOutputStream oos = new ObjectOutputStream(out)) {
|
||||
oos.writeObject(originalChallenge);
|
||||
}
|
||||
data = out.toByteArray();
|
||||
}
|
||||
|
||||
// Deserialize
|
||||
Challenge testChallenge;
|
||||
try (ByteArrayInputStream in = new ByteArrayInputStream(data)) {
|
||||
try (ObjectInputStream ois = new ObjectInputStream(in)) {
|
||||
testChallenge = (Challenge) ois.readObject();
|
||||
}
|
||||
}
|
||||
|
||||
assertThat(testChallenge, not(sameInstance((Challenge) originalChallenge)));
|
||||
assertThat(testChallenge, is(instanceOf(Http01Challenge.class)));
|
||||
assertThat(testChallenge.getType(), is(Http01Challenge.TYPE));
|
||||
assertThat(testChallenge.getStatus(), is(Status.PENDING));
|
||||
assertThat(((Http01Challenge )testChallenge).getToken(), is("rSoI9JpyvFi-ltdnBW0W1DjKstzG7cHixjzcOjwzAEQ"));
|
||||
challenge.unmarshall(getJsonAsObject("updateRegistrationResponse"));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ package org.shredzone.acme4j.challenge;
|
|||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.shredzone.acme4j.util.TestUtils.getJsonAsObject;
|
||||
import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -46,7 +47,7 @@ public class DnsChallengeTest {
|
|||
@Test
|
||||
public void testDnsChallenge() throws IOException {
|
||||
Dns01Challenge challenge = new Dns01Challenge(session);
|
||||
challenge.unmarshall(TestUtils.getJsonAsMap("dnsChallenge"));
|
||||
challenge.unmarshall(getJsonAsObject("dnsChallenge"));
|
||||
|
||||
assertThat(challenge.getType(), is(Dns01Challenge.TYPE));
|
||||
assertThat(challenge.getStatus(), is(Status.PENDING));
|
||||
|
|
|
@ -15,6 +15,7 @@ package org.shredzone.acme4j.challenge;
|
|||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.shredzone.acme4j.util.TestUtils.getJsonAsObject;
|
||||
import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -49,7 +50,7 @@ public class HttpChallengeTest {
|
|||
@Test
|
||||
public void testHttpChallenge() throws IOException {
|
||||
Http01Challenge challenge = new Http01Challenge(session);
|
||||
challenge.unmarshall(TestUtils.getJsonAsMap("httpChallenge"));
|
||||
challenge.unmarshall(getJsonAsObject("httpChallenge"));
|
||||
|
||||
assertThat(challenge.getType(), is(Http01Challenge.TYPE));
|
||||
assertThat(challenge.getStatus(), is(Status.PENDING));
|
||||
|
@ -69,7 +70,7 @@ public class HttpChallengeTest {
|
|||
@Test(expected = AcmeProtocolException.class)
|
||||
public void testNoTokenSet() {
|
||||
Http01Challenge challenge = new Http01Challenge(session);
|
||||
challenge.unmarshall(TestUtils.getJsonAsMap("httpNoTokenChallenge"));
|
||||
challenge.unmarshall(getJsonAsObject("httpNoTokenChallenge"));
|
||||
challenge.getToken();
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ package org.shredzone.acme4j.challenge;
|
|||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.shredzone.acme4j.util.TestUtils.getJsonAsObject;
|
||||
import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -44,7 +45,7 @@ public class OutOfBandChallengeTest {
|
|||
@Test
|
||||
public void testHttpChallenge() throws IOException {
|
||||
OutOfBand01Challenge challenge = new OutOfBand01Challenge(session);
|
||||
challenge.unmarshall(TestUtils.getJsonAsMap("oobChallenge"));
|
||||
challenge.unmarshall(getJsonAsObject("oobChallenge"));
|
||||
|
||||
assertThat(challenge.getType(), is(OutOfBand01Challenge.TYPE));
|
||||
assertThat(challenge.getStatus(), is(Status.PENDING));
|
||||
|
|
|
@ -15,6 +15,7 @@ package org.shredzone.acme4j.challenge;
|
|||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.shredzone.acme4j.util.TestUtils.getJsonAsObject;
|
||||
import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -47,7 +48,7 @@ public class TlsSni01ChallengeTest {
|
|||
@Test
|
||||
public void testTlsSniChallenge() throws IOException {
|
||||
TlsSni01Challenge challenge = new TlsSni01Challenge(session);
|
||||
challenge.unmarshall(TestUtils.getJsonAsMap("tlsSniChallenge"));
|
||||
challenge.unmarshall(getJsonAsObject("tlsSniChallenge"));
|
||||
|
||||
assertThat(challenge.getType(), is(TlsSni01Challenge.TYPE));
|
||||
assertThat(challenge.getStatus(), is(Status.PENDING));
|
||||
|
|
|
@ -15,6 +15,7 @@ package org.shredzone.acme4j.challenge;
|
|||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.shredzone.acme4j.util.TestUtils.getJsonAsObject;
|
||||
import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -46,7 +47,7 @@ public class TlsSni02ChallengeTest {
|
|||
@Test
|
||||
public void testTlsSni02Challenge() throws IOException {
|
||||
TlsSni02Challenge challenge = new TlsSni02Challenge(session);
|
||||
challenge.unmarshall(TestUtils.getJsonAsMap("tlsSni02Challenge"));
|
||||
challenge.unmarshall(getJsonAsObject("tlsSni02Challenge"));
|
||||
|
||||
assertThat(challenge.getType(), is(TlsSni02Challenge.TYPE));
|
||||
assertThat(challenge.getStatus(), is(Status.PENDING));
|
||||
|
|
|
@ -44,6 +44,7 @@ import org.shredzone.acme4j.exception.AcmeException;
|
|||
import org.shredzone.acme4j.exception.AcmeNetworkException;
|
||||
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
||||
import org.shredzone.acme4j.exception.AcmeServerException;
|
||||
import org.shredzone.acme4j.util.JSON;
|
||||
import org.shredzone.acme4j.util.JSONBuilder;
|
||||
import org.shredzone.acme4j.util.TestUtils;
|
||||
|
||||
|
@ -362,11 +363,11 @@ public class DefaultConnectionTest {
|
|||
|
||||
try (DefaultConnection conn = new DefaultConnection(mockHttpConnection) {
|
||||
@Override
|
||||
public Map<String,Object> readJsonResponse() {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
public JSON readJsonResponse() {
|
||||
JSONBuilder result = new JSONBuilder();
|
||||
result.put("type", "urn:zombie:error:apocalypse");
|
||||
result.put("detail", "Zombie apocalypse in progress");
|
||||
return result;
|
||||
return result.toJSON();
|
||||
};
|
||||
}) {
|
||||
conn.conn = mockUrlConnection;
|
||||
|
@ -397,8 +398,8 @@ public class DefaultConnectionTest {
|
|||
|
||||
try (DefaultConnection conn = new DefaultConnection(mockHttpConnection) {
|
||||
@Override
|
||||
public Map<String,Object> readJsonResponse() {
|
||||
return new HashMap<>();
|
||||
public JSON readJsonResponse() {
|
||||
return JSON.empty();
|
||||
};
|
||||
}) {
|
||||
conn.conn = mockUrlConnection;
|
||||
|
@ -553,10 +554,10 @@ public class DefaultConnectionTest {
|
|||
|
||||
try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) {
|
||||
conn.conn = mockUrlConnection;
|
||||
Map<String, Object> result = conn.readJsonResponse();
|
||||
JSON result = conn.readJsonResponse();
|
||||
assertThat(result.keySet(), hasSize(2));
|
||||
assertThat(result, hasEntry("foo", (Object) 123L));
|
||||
assertThat(result, hasEntry("bar", (Object) "a-string"));
|
||||
assertThat(result.get("foo").asInt(), is(123));
|
||||
assertThat(result.get("bar").asString(), is("a-string"));
|
||||
}
|
||||
|
||||
verify(mockUrlConnection).getHeaderField("Content-Type");
|
||||
|
|
|
@ -17,11 +17,11 @@ import java.net.URI;
|
|||
import java.security.cert.X509Certificate;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
import org.shredzone.acme4j.Session;
|
||||
import org.shredzone.acme4j.exception.AcmeException;
|
||||
import org.shredzone.acme4j.util.JSONBuilder;
|
||||
import org.shredzone.acme4j.util.JSON;
|
||||
|
||||
/**
|
||||
* Dummy implementation of {@link Connection} that always fails. Single methods are
|
||||
|
@ -45,7 +45,7 @@ public class DummyConnection implements Connection {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> readJsonResponse() {
|
||||
public JSON readJsonResponse() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
|
|
@ -23,19 +23,16 @@ import java.net.URI;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import org.jose4j.json.JsonUtil;
|
||||
import org.jose4j.lang.JoseException;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.shredzone.acme4j.Authorization;
|
||||
import org.shredzone.acme4j.Session;
|
||||
import org.shredzone.acme4j.exception.AcmeException;
|
||||
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
||||
import org.shredzone.acme4j.provider.TestableConnectionProvider;
|
||||
import org.shredzone.acme4j.util.JSONBuilder;
|
||||
import org.shredzone.acme4j.util.JSON;
|
||||
|
||||
/**
|
||||
* Unit test for {@link ResourceIterator}.
|
||||
|
@ -147,19 +144,14 @@ public class ResourceIteratorTest {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> readJsonResponse() {
|
||||
try {
|
||||
int start = ix * RESOURCES_PER_PAGE;
|
||||
int end = (ix + 1) * RESOURCES_PER_PAGE;
|
||||
public JSON readJsonResponse() {
|
||||
int start = ix * RESOURCES_PER_PAGE;
|
||||
int end = (ix + 1) * RESOURCES_PER_PAGE;
|
||||
|
||||
JSONBuilder cb = new JSONBuilder();
|
||||
cb.array(TYPE, resourceURIs.subList(start, end).toArray());
|
||||
JSONBuilder cb = new JSONBuilder();
|
||||
cb.array(TYPE, resourceURIs.subList(start, end).toArray());
|
||||
|
||||
// Make sure to use the JSON parser
|
||||
return JsonUtil.parseJson(cb.toString());
|
||||
} catch (JoseException ex) {
|
||||
throw new AcmeProtocolException("Invalid JSON", ex);
|
||||
}
|
||||
return JSON.parse(cb.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -19,7 +19,6 @@ import static org.junit.Assert.assertThat;
|
|||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.security.KeyPair;
|
||||
import java.util.Map;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
import org.junit.Before;
|
||||
|
@ -28,6 +27,7 @@ import org.shredzone.acme4j.Session;
|
|||
import org.shredzone.acme4j.challenge.Challenge;
|
||||
import org.shredzone.acme4j.exception.AcmeException;
|
||||
import org.shredzone.acme4j.provider.AcmeProvider;
|
||||
import org.shredzone.acme4j.util.JSON;
|
||||
import org.shredzone.acme4j.util.TestUtils;
|
||||
|
||||
/**
|
||||
|
@ -97,7 +97,7 @@ public class SessionProviderTest {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> directory(Session session, URI serverUri) throws AcmeException {
|
||||
public JSON directory(Session session, URI serverUri) throws AcmeException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
@ -125,7 +125,7 @@ public class SessionProviderTest {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> directory(Session session, URI serverUri) throws AcmeException {
|
||||
public JSON directory(Session session, URI serverUri) throws AcmeException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
|
|
@ -17,14 +17,13 @@ import static org.hamcrest.Matchers.*;
|
|||
import static org.junit.Assert.*;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.shredzone.acme4j.util.TestUtils.getJsonAsObject;
|
||||
import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs;
|
||||
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.jose4j.json.JsonUtil;
|
||||
import org.junit.Test;
|
||||
import org.shredzone.acme4j.Session;
|
||||
import org.shredzone.acme4j.challenge.Challenge;
|
||||
|
@ -35,6 +34,7 @@ import org.shredzone.acme4j.challenge.TlsSni02Challenge;
|
|||
import org.shredzone.acme4j.connector.Connection;
|
||||
import org.shredzone.acme4j.connector.DefaultConnection;
|
||||
import org.shredzone.acme4j.connector.HttpConnector;
|
||||
import org.shredzone.acme4j.util.JSON;
|
||||
import org.shredzone.acme4j.util.TestUtils;
|
||||
|
||||
/**
|
||||
|
@ -84,7 +84,7 @@ public class AbstractAcmeProviderTest {
|
|||
final Session session = mock(Session.class);
|
||||
|
||||
when(connection.accept(any(Integer.class))).thenReturn(HttpURLConnection.HTTP_OK);
|
||||
when(connection.readJsonResponse()).thenReturn(TestUtils.getJsonAsMap("directory"));
|
||||
when(connection.readJsonResponse()).thenReturn(getJsonAsObject("directory"));
|
||||
|
||||
AbstractAcmeProvider provider = new AbstractAcmeProvider() {
|
||||
@Override
|
||||
|
@ -105,8 +105,8 @@ public class AbstractAcmeProviderTest {
|
|||
}
|
||||
};
|
||||
|
||||
Map<String, Object> map = provider.directory(session, testServerUri);
|
||||
assertThat(JsonUtil.toJson(map), sameJSONAs(TestUtils.getJson("directory")));
|
||||
JSON map = provider.directory(session, testServerUri);
|
||||
assertThat(map.toString(), sameJSONAs(TestUtils.getJson("directory")));
|
||||
|
||||
verify(connection).sendRequest(testResolvedUri, session);
|
||||
verify(connection).accept(any(Integer.class));
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.shredzone.acme4j.connector.DummyConnection;
|
|||
import org.shredzone.acme4j.connector.Resource;
|
||||
import org.shredzone.acme4j.exception.AcmeException;
|
||||
import org.shredzone.acme4j.util.JSONBuilder;
|
||||
import org.shredzone.acme4j.util.JSON;
|
||||
import org.shredzone.acme4j.util.TestUtils;
|
||||
|
||||
/**
|
||||
|
@ -84,12 +85,11 @@ public class TestableConnectionProvider extends DummyConnection implements AcmeP
|
|||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> directory(Session session, URI serverUri) throws AcmeException {
|
||||
Map<String, Object> result = directory.toMap();
|
||||
if (result.isEmpty()) {
|
||||
public JSON directory(Session session, URI serverUri) throws AcmeException {
|
||||
if (directory.toMap().isEmpty()) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
return result;
|
||||
return directory.toJSON();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -69,6 +69,11 @@ public class JSONBuilderTest {
|
|||
hasEntry("fooInt", (Object) 456),
|
||||
hasEntry("fooStr", (Object) "String")
|
||||
));
|
||||
|
||||
JSON json = cb.toJSON();
|
||||
assertThat(json.keySet(), hasSize(2));
|
||||
assertThat(json.get("fooInt").asInt(), is(456));
|
||||
assertThat(json.get("fooStr").asString(), is("String"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,285 @@
|
|||
/*
|
||||
* acme4j - Java ACME client
|
||||
*
|
||||
* Copyright (C) 2016 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.util;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.util.Calendar;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
||||
|
||||
/**
|
||||
* Unit test for {@link JSON}.
|
||||
*/
|
||||
public class JSONTest {
|
||||
|
||||
/**
|
||||
* Test that an empty {@link JSON} is empty.
|
||||
*/
|
||||
@Test
|
||||
public void testEmpty() {
|
||||
JSON empty = JSON.empty();
|
||||
assertThat(empty.toString(), is("{}"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test parsers.
|
||||
*/
|
||||
@Test
|
||||
public void testParsers() throws IOException {
|
||||
String json = "{\"foo\":\"a-text\",\n\"bar\":123}";
|
||||
|
||||
JSON fromString = JSON.parse(json);
|
||||
assertThat(fromString.toString(), is(sameJSONAs(json)));
|
||||
|
||||
try (InputStream in = new ByteArrayInputStream(json.getBytes("utf-8"))) {
|
||||
JSON fromStream = JSON.parse(in);
|
||||
assertThat(fromStream.toString(), is(sameJSONAs(json)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that bad JSON fails.
|
||||
*/
|
||||
@Test(expected = AcmeProtocolException.class)
|
||||
public void testParsersBadJSON() throws IOException {
|
||||
JSON.parse("This is no JSON.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test all object related methods.
|
||||
*/
|
||||
@Test
|
||||
public void testObject() {
|
||||
JSON json = TestUtils.getJsonAsObject("json");
|
||||
|
||||
assertThat(json.keySet(), containsInAnyOrder(
|
||||
"text", "number", "uri", "url", "date", "array", "collect"));
|
||||
assertThat(json.contains("text"), is(true));
|
||||
assertThat(json.contains("music"), is(false));
|
||||
assertThat(json.get("text"), is(notNullValue()));
|
||||
assertThat(json.get("music"), is(notNullValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test all array related methods.
|
||||
*/
|
||||
@Test
|
||||
public void testArray() {
|
||||
JSON json = TestUtils.getJsonAsObject("json");
|
||||
JSON.Array array = json.get("array").asArray();
|
||||
|
||||
assertThat(array.size(), is(4));
|
||||
assertThat(array.get(0), is(notNullValue()));
|
||||
assertThat(array.get(1), is(notNullValue()));
|
||||
assertThat(array.get(2), is(notNullValue()));
|
||||
assertThat(array.get(3), is(notNullValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test all array iterator related methods.
|
||||
*/
|
||||
@Test
|
||||
public void testArrayIterator() {
|
||||
JSON json = TestUtils.getJsonAsObject("json");
|
||||
JSON.Array array = json.get("array").asArray();
|
||||
|
||||
Iterator<JSON.Value> it = array.iterator();
|
||||
assertThat(it, is(notNullValue()));
|
||||
|
||||
assertThat(it.hasNext(), is(true));
|
||||
assertThat(it.next().asString(), is("foo"));
|
||||
|
||||
assertThat(it.hasNext(), is(true));
|
||||
assertThat(it.next().asInt(), is(987));
|
||||
|
||||
assertThat(it.hasNext(), is(true));
|
||||
assertThat(it.next().asArray().size(), is(3));
|
||||
|
||||
assertThat(it.hasNext(), is(true));
|
||||
try {
|
||||
it.remove();
|
||||
fail("was able to remove from array");
|
||||
} catch (UnsupportedOperationException ex) {
|
||||
// expected
|
||||
}
|
||||
assertThat(it.next().asObject(), is(notNullValue()));
|
||||
|
||||
assertThat(it.hasNext(), is(false));
|
||||
try {
|
||||
it.next();
|
||||
fail("next past last element");
|
||||
} catch (NoSuchElementException ex) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test all getters on existing values.
|
||||
*/
|
||||
@Test
|
||||
public void testGetter() throws MalformedURLException {
|
||||
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
|
||||
cal.clear();
|
||||
cal.set(2016, 0, 8);
|
||||
|
||||
JSON json = TestUtils.getJsonAsObject("json");
|
||||
|
||||
assertThat(json.get("text").asString(), is("lorem ipsum"));
|
||||
assertThat(json.get("number").asInt(), is(123));
|
||||
assertThat(json.get("uri").asURI(), is(URI.create("mailto:foo@example.com")));
|
||||
assertThat(json.get("url").asURL(), is(new URL("http://example.com")));
|
||||
assertThat(json.get("date").asDate(), is(cal.getTime()));
|
||||
|
||||
JSON.Array array = json.get("array").asArray();
|
||||
assertThat(array.get(0).asString(), is("foo"));
|
||||
assertThat(array.get(1).asInt(), is(987));
|
||||
|
||||
JSON.Array array2 = array.get(2).asArray();
|
||||
assertThat(array2.get(0).asInt(), is(1));
|
||||
assertThat(array2.get(1).asInt(), is(2));
|
||||
assertThat(array2.get(2).asInt(), is(3));
|
||||
|
||||
JSON sub = array.get(3).asObject();
|
||||
assertThat(sub.get("test").asString(), is("ok"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that getters are null safe.
|
||||
*/
|
||||
@Test
|
||||
public void testNullGetter() throws MalformedURLException {
|
||||
JSON json = TestUtils.getJsonAsObject("json");
|
||||
|
||||
assertThat(json.get("none"), is(notNullValue()));
|
||||
assertThat(json.get("none").asString(), is(nullValue()));
|
||||
assertThat(json.get("none").asURI(), is(nullValue()));
|
||||
assertThat(json.get("none").asURL(), is(nullValue()));
|
||||
assertThat(json.get("none").asDate(), is(nullValue()));
|
||||
assertThat(json.get("none").asArray(), is(nullValue()));
|
||||
assertThat(json.get("none").asObject(), is(nullValue()));
|
||||
|
||||
try {
|
||||
json.get("none").asInt();
|
||||
fail("asInt did not fail");
|
||||
} catch (AcmeProtocolException ex) {
|
||||
// expected
|
||||
}
|
||||
|
||||
try {
|
||||
json.get("none").required();
|
||||
fail("required did not fail");
|
||||
} catch (AcmeProtocolException ex) {
|
||||
// expected
|
||||
}
|
||||
|
||||
JSON.Value textv = json.get("text");
|
||||
assertThat(textv.required(), is(textv));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that wrong getters return an exception.
|
||||
*/
|
||||
@Test
|
||||
public void testWrongGetter() throws MalformedURLException {
|
||||
JSON json = TestUtils.getJsonAsObject("json");
|
||||
|
||||
try {
|
||||
json.get("text").asObject();
|
||||
fail("no exception was thrown");
|
||||
} catch (AcmeProtocolException ex) {
|
||||
// expected
|
||||
}
|
||||
|
||||
try {
|
||||
json.get("text").asArray();
|
||||
fail("no exception was thrown");
|
||||
} catch (AcmeProtocolException ex) {
|
||||
// expected
|
||||
}
|
||||
|
||||
try {
|
||||
json.get("text").asInt();
|
||||
fail("no exception was thrown");
|
||||
} catch (AcmeProtocolException ex) {
|
||||
// expected
|
||||
}
|
||||
|
||||
try {
|
||||
json.get("text").asURI();
|
||||
fail("no exception was thrown");
|
||||
} catch (AcmeProtocolException ex) {
|
||||
// expected
|
||||
}
|
||||
|
||||
try {
|
||||
json.get("text").asURL();
|
||||
fail("no exception was thrown");
|
||||
} catch (AcmeProtocolException ex) {
|
||||
// expected
|
||||
}
|
||||
|
||||
try {
|
||||
json.get("text").asDate();
|
||||
fail("no exception was thrown");
|
||||
} catch (AcmeProtocolException ex) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that serialization works correctly.
|
||||
*/
|
||||
@Test
|
||||
public void testSerialization() throws IOException, ClassNotFoundException {
|
||||
JSON originalJson = TestUtils.getJsonAsObject("newAuthorizationResponse");
|
||||
|
||||
// Serialize
|
||||
byte[] data;
|
||||
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
|
||||
try (ObjectOutputStream oos = new ObjectOutputStream(out)) {
|
||||
oos.writeObject(originalJson);
|
||||
}
|
||||
data = out.toByteArray();
|
||||
}
|
||||
|
||||
// Deserialize
|
||||
JSON testJson;
|
||||
try (ByteArrayInputStream in = new ByteArrayInputStream(data)) {
|
||||
try (ObjectInputStream ois = new ObjectInputStream(in)) {
|
||||
testJson = (JSON) ois.readObject();
|
||||
}
|
||||
}
|
||||
|
||||
assertThat(testJson, not(sameInstance(originalJson)));
|
||||
assertThat(testJson.toString(), not(isEmptyOrNullString()));
|
||||
assertThat(testJson.toString(), is(sameJSONAs(originalJson.toString())));
|
||||
}
|
||||
|
||||
}
|
|
@ -46,7 +46,6 @@ import org.jose4j.base64url.Base64Url;
|
|||
import org.jose4j.json.JsonUtil;
|
||||
import org.jose4j.jwk.JsonWebKey;
|
||||
import org.jose4j.jwk.JsonWebKey.OutputControlLevel;
|
||||
import org.jose4j.lang.JoseException;
|
||||
import org.shredzone.acme4j.Session;
|
||||
import org.shredzone.acme4j.provider.AcmeProvider;
|
||||
|
||||
|
@ -109,12 +108,8 @@ public final class TestUtils {
|
|||
* JSON resource
|
||||
* @return Parsed JSON resource
|
||||
*/
|
||||
public static Map<String, Object> getJsonAsMap(String key) {
|
||||
try {
|
||||
return JsonUtil.parseJson(getJson(key));
|
||||
} catch (JoseException ex) {
|
||||
throw new RuntimeException("JSON error", ex);
|
||||
}
|
||||
public static JSON getJsonAsObject(String key) {
|
||||
return JSON.parse(getJson(key));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -34,6 +34,16 @@ directoryNoMeta = \
|
|||
"new-cert": "https://example.com/acme/new-cert"\
|
||||
}
|
||||
|
||||
json = \
|
||||
{\
|
||||
"text": "lorem ipsum",\
|
||||
"number": 123,\
|
||||
"uri": "mailto:foo@example.com",\
|
||||
"url": "http://example.com",\
|
||||
"date": "2016-01-08T00:00:00Z",\
|
||||
"array": ["foo", 987, [1, 2, 3], {"test": "ok"}],\
|
||||
"collect": ["foo", "bar", "barfoo"]\
|
||||
}
|
||||
|
||||
newRegistration = \
|
||||
{"resource":"new-reg",\
|
||||
|
|
Loading…
Reference in New Issue