From 3923db0677c170119eb934b2ee506a77da759a42 Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Tue, 20 Nov 2018 11:03:47 +0000 Subject: [PATCH] Modify MaxMind-DB-Reader-java to remove the dependency on the large com.fasterxml.jackson.databind JSON package, and use POJOs instead. --- router/java/src/com/maxmind/db/CHMCache.java | 10 ++- router/java/src/com/maxmind/db/Decoder.java | 70 +++++++++---------- router/java/src/com/maxmind/db/Metadata.java | 61 +++++++++------- router/java/src/com/maxmind/db/NoCache.java | 4 +- router/java/src/com/maxmind/db/NodeCache.java | 6 +- router/java/src/com/maxmind/db/Reader.java | 9 ++- 6 files changed, 80 insertions(+), 80 deletions(-) diff --git a/router/java/src/com/maxmind/db/CHMCache.java b/router/java/src/com/maxmind/db/CHMCache.java index 058db62d91..adcfbd52d7 100644 --- a/router/java/src/com/maxmind/db/CHMCache.java +++ b/router/java/src/com/maxmind/db/CHMCache.java @@ -3,8 +3,6 @@ package com.maxmind.db; import java.io.IOException; import java.util.concurrent.ConcurrentHashMap; -import com.fasterxml.jackson.databind.JsonNode; - /** * A simplistic cache using a {@link ConcurrentHashMap}. There's no eviction * policy, it just fills up until reaching the specified capacity <small>(or @@ -15,7 +13,7 @@ public class CHMCache implements NodeCache { private static final int DEFAULT_CAPACITY = 4096; private final int capacity; - private final ConcurrentHashMap<Integer, JsonNode> cache; + private final ConcurrentHashMap<Integer, Object> cache; private boolean cacheFull = false; public CHMCache() { @@ -24,13 +22,13 @@ public class CHMCache implements NodeCache { public CHMCache(int capacity) { this.capacity = capacity; - this.cache = new ConcurrentHashMap<Integer, JsonNode>(capacity); + this.cache = new ConcurrentHashMap<Integer, Object>(capacity); } @Override - public JsonNode get(int key, Loader loader) throws IOException { + public Object get(int key, Loader loader) throws IOException { Integer k = key; - JsonNode value = cache.get(k); + Object value = cache.get(k); if (value == null) { value = loader.load(key); if (!cacheFull) { diff --git a/router/java/src/com/maxmind/db/Decoder.java b/router/java/src/com/maxmind/db/Decoder.java index 5396a11881..0ca4774ffa 100644 --- a/router/java/src/com/maxmind/db/Decoder.java +++ b/router/java/src/com/maxmind/db/Decoder.java @@ -12,10 +12,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.*; - /* * Decoder for MaxMind DB data. * @@ -25,8 +21,6 @@ final class Decoder { private static final Charset UTF_8 = Charset.forName("UTF-8"); - private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); - private static final int[] POINTER_VALUE_OFFSETS = { 0, 0, 1 << 11, (1 << 19) + ((1) << 11), 0 }; // XXX - This is only for unit testings. We should possibly make a @@ -71,12 +65,12 @@ final class Decoder { private final NodeCache.Loader cacheLoader = new NodeCache.Loader() { @Override - public JsonNode load(int key) throws IOException { + public Object load(int key) throws IOException { return decode(key); } }; - JsonNode decode(int offset) throws IOException { + Object decode(int offset) throws IOException { if (offset >= this.buffer.capacity()) { throw new InvalidDatabaseException( "The MaxMind DB file's data section contains bad data: " @@ -87,7 +81,7 @@ final class Decoder { return decode(); } - JsonNode decode() throws IOException { + Object decode() throws IOException { int ctrlByte = 0xFF & this.buffer.get(); Type type = Type.fromControlByte(ctrlByte); @@ -103,12 +97,12 @@ final class Decoder { // for unit testing if (this.POINTER_TEST_HACK) { - return new LongNode(pointer); + return Long.valueOf(pointer); } int targetOffset = (int) pointer; int position = buffer.position(); - JsonNode node = cache.get(targetOffset, cacheLoader); + Object node = cache.get(targetOffset, cacheLoader); buffer.position(position); return node; } @@ -147,7 +141,7 @@ final class Decoder { return this.decodeByType(type, size); } - private JsonNode decodeByType(Type type, int size) + private Object decodeByType(Type type, int size) throws IOException { switch (type) { case MAP: @@ -157,13 +151,13 @@ final class Decoder { case BOOLEAN: return Decoder.decodeBoolean(size); case UTF8_STRING: - return new TextNode(this.decodeString(size)); + return this.decodeString(size); case DOUBLE: return this.decodeDouble(size); case FLOAT: return this.decodeFloat(size); case BYTES: - return new BinaryNode(this.getByteArray(size)); + return this.getByteArray(size); case UINT16: return this.decodeUint16(size); case UINT32: @@ -188,12 +182,12 @@ final class Decoder { return s; } - private IntNode decodeUint16(int size) { - return new IntNode(this.decodeInteger(size)); + private Integer decodeUint16(int size) { + return Integer.valueOf(this.decodeInteger(size)); } - private IntNode decodeInt32(int size) { - return new IntNode(this.decodeInteger(size)); + private Integer decodeInt32(int size) { + return Integer.valueOf(this.decodeInteger(size)); } private long decodeLong(int size) { @@ -204,8 +198,8 @@ final class Decoder { return integer; } - private LongNode decodeUint32(int size) { - return new LongNode(this.decodeLong(size)); + private Long decodeUint32(int size) { + return Long.valueOf(this.decodeLong(size)); } private int decodeInteger(int size) { @@ -224,36 +218,36 @@ final class Decoder { return integer; } - private BigIntegerNode decodeBigInteger(int size) { + private BigInteger decodeBigInteger(int size) { byte[] bytes = this.getByteArray(size); - return new BigIntegerNode(new BigInteger(1, bytes)); + return new BigInteger(1, bytes); } - private DoubleNode decodeDouble(int size) throws InvalidDatabaseException { + private Double decodeDouble(int size) throws InvalidDatabaseException { if (size != 8) { throw new InvalidDatabaseException( "The MaxMind DB file's data section contains bad data: " + "invalid size of double."); } - return new DoubleNode(this.buffer.getDouble()); + return Double.valueOf(this.buffer.getDouble()); } - private FloatNode decodeFloat(int size) throws InvalidDatabaseException { + private Float decodeFloat(int size) throws InvalidDatabaseException { if (size != 4) { throw new InvalidDatabaseException( "The MaxMind DB file's data section contains bad data: " + "invalid size of float."); } - return new FloatNode(this.buffer.getFloat()); + return Float.valueOf(this.buffer.getFloat()); } - private static BooleanNode decodeBoolean(int size) + private static Boolean decodeBoolean(int size) throws InvalidDatabaseException { switch (size) { case 0: - return BooleanNode.FALSE; + return Boolean.FALSE; case 1: - return BooleanNode.TRUE; + return Boolean.TRUE; default: throw new InvalidDatabaseException( "The MaxMind DB file's data section contains bad data: " @@ -261,28 +255,28 @@ final class Decoder { } } - private JsonNode decodeArray(int size) throws IOException { + private List<Object> decodeArray(int size) throws IOException { - List<JsonNode> array = new ArrayList<JsonNode>(size); + List<Object> array = new ArrayList<Object>(size); for (int i = 0; i < size; i++) { - JsonNode r = this.decode(); + Object r = this.decode(); array.add(r); } - return new ArrayNode(OBJECT_MAPPER.getNodeFactory(), Collections.unmodifiableList(array)); + return Collections.unmodifiableList(array); } - private JsonNode decodeMap(int size) throws IOException { + private Map<String, Object> decodeMap(int size) throws IOException { int capacity = (int) (size / 0.75F + 1.0F); - Map<String, JsonNode> map = new HashMap<String, JsonNode>(capacity); + Map<String, Object> map = new HashMap<String, Object>(capacity); for (int i = 0; i < size; i++) { - String key = this.decode().asText(); - JsonNode value = this.decode(); + String key = (String) this.decode(); + Object value = this.decode(); map.put(key, value); } - return new ObjectNode(OBJECT_MAPPER.getNodeFactory(), Collections.unmodifiableMap(map)); + return Collections.unmodifiableMap(map); } private byte[] getByteArray(int length) { diff --git a/router/java/src/com/maxmind/db/Metadata.java b/router/java/src/com/maxmind/db/Metadata.java index e31bd25920..b15d256b62 100644 --- a/router/java/src/com/maxmind/db/Metadata.java +++ b/router/java/src/com/maxmind/db/Metadata.java @@ -6,10 +6,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; - public final class Metadata { private final int binaryFormatMajorVersion; private final int binaryFormatMinorVersion; @@ -18,11 +14,11 @@ public final class Metadata { private final String databaseType; - private final JsonNode description; + private final Map description; private final int ipVersion; - private final JsonNode languages; + private final List languages; private final int nodeByteSize; @@ -32,22 +28,43 @@ public final class Metadata { private final int searchTreeSize; - Metadata(JsonNode metadata) { - this.binaryFormatMajorVersion = metadata.get( - "binary_format_major_version").asInt(); - this.binaryFormatMinorVersion = metadata.get( - "binary_format_minor_version").asInt(); - this.buildEpoch = metadata.get("build_epoch").asLong(); - this.databaseType = metadata.get("database_type").asText(); - this.languages = metadata.get("languages"); - this.description = metadata.get("description"); - this.ipVersion = metadata.get("ip_version").asInt(); - this.nodeCount = metadata.get("node_count").asInt(); - this.recordSize = metadata.get("record_size").asInt(); + Metadata(Map metadata) { + this.binaryFormatMajorVersion = getInt(metadata, + "binary_format_major_version"); + this.binaryFormatMinorVersion = getInt(metadata, + "binary_format_minor_version"); + this.buildEpoch = getLong(metadata, "build_epoch"); + this.databaseType = getString(metadata, "database_type"); + this.languages = (List) metadata.get("languages"); + this.description = (Map) metadata.get("description"); + this.ipVersion = getInt(metadata, "ip_version"); + this.nodeCount = getInt(metadata, "node_count"); + this.recordSize = getInt(metadata, "record_size"); this.nodeByteSize = this.recordSize / 4; this.searchTreeSize = this.nodeCount * this.nodeByteSize; } + private static int getInt(Object m, String key) { + Map map = (Map) m; + Number i = (Number) map.get(key); + if (i != null) + return i.intValue(); + return 0; + } + + private static long getLong(Object m, String key) { + Map map = (Map) m; + Number i = (Number) map.get(key); + if (i != null) + return i.longValue(); + return 0; + } + + private static String getString(Object m, String key) { + Map map = (Map) m; + return (String) map.get(key); + } + /** * @return the major version number for the database's binary format. */ @@ -82,9 +99,7 @@ public final class Metadata { * @return map from language code to description in that language. */ public Map<String, String> getDescription() { - return new ObjectMapper().convertValue(this.description, - new TypeReference<HashMap<String, String>>() { - }); + return this.description; } /** @@ -99,9 +114,7 @@ public final class Metadata { * @return list of languages supported by the database. */ public List<String> getLanguages() { - return new ObjectMapper().convertValue(this.languages, - new TypeReference<ArrayList<String>>() { - }); + return this.languages; } /** diff --git a/router/java/src/com/maxmind/db/NoCache.java b/router/java/src/com/maxmind/db/NoCache.java index 45276a2767..c6f26814d1 100644 --- a/router/java/src/com/maxmind/db/NoCache.java +++ b/router/java/src/com/maxmind/db/NoCache.java @@ -2,8 +2,6 @@ package com.maxmind.db; import java.io.IOException; -import com.fasterxml.jackson.databind.JsonNode; - /** * A no-op cache singleton. */ @@ -15,7 +13,7 @@ public class NoCache implements NodeCache { } @Override - public JsonNode get(int key, Loader loader) throws IOException { + public Object get(int key, Loader loader) throws IOException { return loader.load(key); } diff --git a/router/java/src/com/maxmind/db/NodeCache.java b/router/java/src/com/maxmind/db/NodeCache.java index f1c7363546..cd272c1afc 100644 --- a/router/java/src/com/maxmind/db/NodeCache.java +++ b/router/java/src/com/maxmind/db/NodeCache.java @@ -2,14 +2,12 @@ package com.maxmind.db; import java.io.IOException; -import com.fasterxml.jackson.databind.JsonNode; - public interface NodeCache { public interface Loader { - JsonNode load(int key) throws IOException; + Object load(int key) throws IOException; } - public JsonNode get(int key, Loader loader) throws IOException; + public Object get(int key, Loader loader) throws IOException; } diff --git a/router/java/src/com/maxmind/db/Reader.java b/router/java/src/com/maxmind/db/Reader.java index 32d0b86457..65a705097f 100644 --- a/router/java/src/com/maxmind/db/Reader.java +++ b/router/java/src/com/maxmind/db/Reader.java @@ -6,10 +6,9 @@ import java.io.IOException; import java.io.InputStream; import java.net.InetAddress; import java.nio.ByteBuffer; +import java.util.Map; import java.util.concurrent.atomic.AtomicReference; -import com.fasterxml.jackson.databind.JsonNode; - /** * Instances of this class provide a reader for the MaxMind DB format. IP * addresses can be looked up using the <code>get</code> method. @@ -129,7 +128,7 @@ public final class Reader implements Closeable { int start = this.findMetadataStart(buffer, name); Decoder metadataDecoder = new Decoder(this.cache, buffer, start); - this.metadata = new Metadata(metadataDecoder.decode(start)); + this.metadata = new Metadata((Map) metadataDecoder.decode(start)); this.ipV4Start = this.findIpV4StartNode(buffer); } @@ -141,7 +140,7 @@ public final class Reader implements Closeable { * @return the record for the IP address. * @throws IOException if a file I/O error occurs. */ - public JsonNode get(InetAddress ipAddress) throws IOException { + public Object get(InetAddress ipAddress) throws IOException { ByteBuffer buffer = this.getBufferHolder().get(); int pointer = this.findAddressInTree(buffer, ipAddress); if (pointer == 0) { @@ -234,7 +233,7 @@ public final class Reader implements Closeable { } } - private JsonNode resolveDataPointer(ByteBuffer buffer, int pointer) + private Object resolveDataPointer(ByteBuffer buffer, int pointer) throws IOException { int resolved = (pointer - this.metadata.getNodeCount()) + this.metadata.getSearchTreeSize(); -- GitLab