From 658edd901def7b997a26c456ff23373788133c81 Mon Sep 17 00:00:00 2001 From: Joshua Hight Date: Fri, 17 Apr 2020 16:58:47 -0700 Subject: [PATCH] use custom deserialization to handle list extensions --- src/io/calidog/certstream/CertStream.java | 16 ++++- .../certstream/CertStreamCertificate.java | 4 +- .../certstream/CertStreamCertificatePOJO.java | 4 +- ...CertStreamCertificatePOJODeserializer.java | 62 +++++++++++++++++++ 4 files changed, 80 insertions(+), 6 deletions(-) create mode 100644 src/io/calidog/certstream/CertStreamCertificatePOJODeserializer.java diff --git a/src/io/calidog/certstream/CertStream.java b/src/io/calidog/certstream/CertStream.java index 0144cfa..5664c0e 100644 --- a/src/io/calidog/certstream/CertStream.java +++ b/src/io/calidog/certstream/CertStream.java @@ -1,6 +1,7 @@ package io.calidog.certstream; import com.google.gson.Gson; +import com.google.gson.GsonBuilder; import com.google.gson.JsonSyntaxException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -60,13 +61,13 @@ public static void onMessage(CertStreamMessageHandler handler) CertStreamMessagePOJO msg; try { - msg = new Gson().fromJson(string, CertStreamMessagePOJO.class); + msg = certStreamGson.fromJson(string, CertStreamMessagePOJO.class); if (msg.messageType.equalsIgnoreCase("heartbeat")) { return; } - }catch (JsonSyntaxException e) + } catch (JsonSyntaxException e) { System.out.println(e.getMessage()); logger.warn("onMessage had an exception parsing some json", e); @@ -87,6 +88,15 @@ public static void onMessage(CertStreamMessageHandler handler) }); } + private static Gson certStreamGson = + new GsonBuilder() + .registerTypeAdapter + ( + CertStreamCertificatePOJO.class, + new CertStreamCertificatePOJODeserializer() + ) + .create(); + /** * @param handler A {@link Consumer} that we'll * run in a Thread that stays alive as long @@ -99,7 +109,7 @@ public static void onMessageAlternativeServer (CertStreamMessageHandler handler, CertStreamMessagePOJO msg; try { - msg = new Gson().fromJson(string, CertStreamMessagePOJO.class); + msg = certStreamGson.fromJson(string, CertStreamMessagePOJO.class); if (msg.messageType.equalsIgnoreCase("heartbeat")) { return; diff --git a/src/io/calidog/certstream/CertStreamCertificate.java b/src/io/calidog/certstream/CertStreamCertificate.java index e9956ef..710f54f 100644 --- a/src/io/calidog/certstream/CertStreamCertificate.java +++ b/src/io/calidog/certstream/CertStreamCertificate.java @@ -16,7 +16,7 @@ */ public class CertStreamCertificate extends X509Certificate { private HashMap subject; - private HashMap extensions; + private HashMap extensions; private double notBefore; private double notAfter; @@ -257,7 +257,7 @@ public byte[] getExtensionValue(String s) { * passed-in oid String. The oid string is represented * by whatever CertStream passes us. */ - public String getStringExtensionValue(String key) + public String[] getStringExtensionValue(String key) { return extensions.get(key); } diff --git a/src/io/calidog/certstream/CertStreamCertificatePOJO.java b/src/io/calidog/certstream/CertStreamCertificatePOJO.java index 8b2f5a3..a4717a8 100644 --- a/src/io/calidog/certstream/CertStreamCertificatePOJO.java +++ b/src/io/calidog/certstream/CertStreamCertificatePOJO.java @@ -12,7 +12,9 @@ public class CertStreamCertificatePOJO { HashMap subject; - HashMap extensions; + // values can be either strings or lists of strings, so we use a a custom deserializer + // that converts strings into singleton arrays + HashMap extensions; @SerializedName("not_before") double notBefore; diff --git a/src/io/calidog/certstream/CertStreamCertificatePOJODeserializer.java b/src/io/calidog/certstream/CertStreamCertificatePOJODeserializer.java new file mode 100644 index 0000000..0be5f5e --- /dev/null +++ b/src/io/calidog/certstream/CertStreamCertificatePOJODeserializer.java @@ -0,0 +1,62 @@ +package io.calidog.certstream; + +import com.google.gson.*; + +import java.lang.reflect.Type; +import java.util.HashMap; + +public class CertStreamCertificatePOJODeserializer implements JsonDeserializer { + + @Override + public CertStreamCertificatePOJO deserialize( + JsonElement jsonElement, + Type type, + JsonDeserializationContext jsonDeserializationContext + ) throws JsonParseException { + JsonObject jsonObj = jsonElement.getAsJsonObject(); + + JsonObject jsonExtensions; + + HashMap extensionMap = null; + + if (jsonObj.has("extensions")) + { + jsonExtensions = jsonObj.remove("extensions").getAsJsonObject(); + + final HashMap finalExtensionMap = new HashMap<>(jsonExtensions.size()); + + jsonExtensions + .entrySet() + .forEach + ( + (java.util.Map.Entry entry) -> + { + String key = entry.getKey(); + JsonElement value = entry.getValue(); + String[] extensionValueList; + try { + extensionValueList = new String[] { value.getAsString() }; + } catch (IllegalStateException | UnsupportedOperationException e) { + JsonArray extensionJsonArray = value.getAsJsonArray(); + extensionValueList = new String[extensionJsonArray.size()]; + + for (int i = 0; i < extensionJsonArray.size(); i++) { + extensionValueList[i] = extensionJsonArray.get(i).getAsString(); + } + } + + finalExtensionMap.put(key, extensionValueList); + } + ); + + extensionMap = finalExtensionMap; + } + + CertStreamCertificatePOJO retVal = + jsonDeserializationContext.deserialize(jsonElement, type); + + retVal.extensions = extensionMap; + + return retVal; + } +}