Modify GeoIP2-java

to remove the dependency on the large com.fasterxml.jackson.databind JSON package,
and use POJOs instead.
Add main() for testing
This commit is contained in:
zzz
2018-11-20 11:05:46 +00:00
parent 3923db0677
commit 21ca75da14

View File

@ -1,12 +1,7 @@
package com.maxmind.geoip2;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.maxmind.db.*;
import com.maxmind.db.Reader.FileMode;
import com.maxmind.geoip2.exception.AddressNotFoundException;
import com.maxmind.geoip2.exception.GeoIp2Exception;
import com.maxmind.geoip2.model.*;
import java.io.Closeable;
import java.io.File;
@ -15,8 +10,11 @@ import java.io.InputStream;
import java.net.InetAddress;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* Modified and simplified for I2P
*
* <p>
* The class {@code DatabaseReader} provides a reader for the GeoIP2 database
* format.
@ -50,13 +48,13 @@ import java.util.List;
* {@code com.maxmind.db.CHMCache}. Using this cache, lookup performance is
* significantly improved at the cost of a small (~2MB) memory overhead.
* </p>
*
* @since 0.9.38
*/
public class DatabaseReader implements DatabaseProvider, Closeable {
public class DatabaseReader implements Closeable {
private final Reader reader;
private final ObjectMapper om;
private final List<String> locales;
private DatabaseReader(Builder builder) throws IOException {
@ -70,12 +68,6 @@ public class DatabaseReader implements DatabaseProvider, Closeable {
throw new IllegalArgumentException(
"Unsupported Builder configuration: expected either File or URL");
}
this.om = new ObjectMapper();
this.om.configure(MapperFeature.CAN_OVERRIDE_ACCESS_MODIFIERS, false);
this.om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
false);
this.om.configure(
DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, true);
this.locales = builder.locales;
}
@ -162,13 +154,31 @@ public class DatabaseReader implements DatabaseProvider, Closeable {
}
/**
* Returns a map containing:
*
*<ul><li>continent: Map containing:
* <ul><li>code: String
* <li>names: Map of lang to translated name
* <li>geoname_id: Long
* </ul>
*<ul><li>country: Map containing:
* <ul><li>iso_code: String
* <li>names: Map of lang to translated name
* <li>geoname_id: Long
* </ul>
*<ul><li>registered_country: Map containing:
* <ul><li>iso_code: String
* <li>names: Map of lang to translated name
* <li>geoname_id: Long
* </ul>
*</ul>
*
* @param ipAddress IPv4 or IPv6 address to lookup.
* @return A <T> object with the data for the IP address
* @return A Map with the data for the IP address
* @throws IOException if there is an error opening or reading from the file.
* @throws AddressNotFoundException if the IP address is not in our database
*/
private <T> T get(InetAddress ipAddress, Class<T> cls,
String type) throws IOException, AddressNotFoundException {
private Object get(InetAddress ipAddress,
String type) throws IOException {
String databaseType = this.getMetadata().getDatabaseType();
if (!databaseType.contains(type)) {
@ -179,27 +189,7 @@ public class DatabaseReader implements DatabaseProvider, Closeable {
+ " database using the " + caller + " method");
}
ObjectNode node = jsonNodeToObjectNode(reader.get(ipAddress));
// We throw the same exception as the web service when an IP is not in
// the database
if (node == null) {
throw new AddressNotFoundException("The address "
+ ipAddress.getHostAddress() + " is not in the database.");
}
InjectableValues inject = new JsonInjector(locales, ipAddress.getHostAddress());
return this.om.reader(inject).treeToValue(node, cls);
}
private ObjectNode jsonNodeToObjectNode(JsonNode node)
throws InvalidDatabaseException {
if (node == null || node instanceof ObjectNode) {
return (ObjectNode) node;
}
throw new InvalidDatabaseException(
"Unexpected data type returned. The GeoIP2 database may be corrupt.");
return reader.get(ipAddress);
}
/**
@ -221,103 +211,21 @@ public class DatabaseReader implements DatabaseProvider, Closeable {
this.reader.close();
}
@Override
public CountryResponse country(InetAddress ipAddress) throws IOException,
GeoIp2Exception {
return this.get(ipAddress, CountryResponse.class, "Country");
}
public String country(String ipAddress) throws IOException {
InetAddress ia = InetAddress.getByName(ipAddress);
Object o = get(ia, "Country");
if (!(o instanceof Map))
return null;
Map m = (Map) o;
o = m.get("country");
if (!(o instanceof Map))
return null;
m = (Map) o;
o = m.get("iso_code");
if (!(o instanceof String))
return null;
return (String) o;
@Override
public CityResponse city(InetAddress ipAddress) throws IOException,
GeoIp2Exception {
return this.get(ipAddress, CityResponse.class, "City");
}
/**
* Look up an IP address in a GeoIP2 Anonymous IP.
*
* @param ipAddress IPv4 or IPv6 address to lookup.
* @return a AnonymousIpResponse for the requested IP address.
* @throws GeoIp2Exception if there is an error looking up the IP
* @throws IOException if there is an IO error
*/
@Override
public AnonymousIpResponse anonymousIp(InetAddress ipAddress) throws IOException,
GeoIp2Exception {
return this.get(ipAddress, AnonymousIpResponse.class, "GeoIP2-Anonymous-IP");
}
/**
* Look up an IP address in a GeoLite2 ASN database.
*
* @param ipAddress IPv4 or IPv6 address to lookup.
* @return an AsnResponse for the requested IP address.
* @throws GeoIp2Exception if there is an error looking up the IP
* @throws IOException if there is an IO error
*/
@Override
public AsnResponse asn(InetAddress ipAddress) throws IOException,
GeoIp2Exception {
return this.get(ipAddress, AsnResponse.class, "GeoLite2-ASN");
}
/**
* Look up an IP address in a GeoIP2 Connection Type database.
*
* @param ipAddress IPv4 or IPv6 address to lookup.
* @return a ConnectTypeResponse for the requested IP address.
* @throws GeoIp2Exception if there is an error looking up the IP
* @throws IOException if there is an IO error
*/
@Override
public ConnectionTypeResponse connectionType(InetAddress ipAddress)
throws IOException, GeoIp2Exception {
return this.get(ipAddress, ConnectionTypeResponse.class,
"GeoIP2-Connection-Type");
}
/**
* Look up an IP address in a GeoIP2 Domain database.
*
* @param ipAddress IPv4 or IPv6 address to lookup.
* @return a DomainResponse for the requested IP address.
* @throws GeoIp2Exception if there is an error looking up the IP
* @throws IOException if there is an IO error
*/
@Override
public DomainResponse domain(InetAddress ipAddress) throws IOException,
GeoIp2Exception {
return this
.get(ipAddress, DomainResponse.class, "GeoIP2-Domain");
}
/**
* Look up an IP address in a GeoIP2 Enterprise database.
*
* @param ipAddress IPv4 or IPv6 address to lookup.
* @return an EnterpriseResponse for the requested IP address.
* @throws GeoIp2Exception if there is an error looking up the IP
* @throws IOException if there is an IO error
*/
@Override
public EnterpriseResponse enterprise(InetAddress ipAddress) throws IOException,
GeoIp2Exception {
return this.get(ipAddress, EnterpriseResponse.class, "Enterprise");
}
/**
* Look up an IP address in a GeoIP2 ISP database.
*
* @param ipAddress IPv4 or IPv6 address to lookup.
* @return an IspResponse for the requested IP address.
* @throws GeoIp2Exception if there is an error looking up the IP
* @throws IOException if there is an IO error
*/
@Override
public IspResponse isp(InetAddress ipAddress) throws IOException,
GeoIp2Exception {
return this.get(ipAddress, IspResponse.class, "GeoIP2-ISP");
}
/**
@ -326,4 +234,18 @@ public class DatabaseReader implements DatabaseProvider, Closeable {
public Metadata getMetadata() {
return this.reader.getMetadata();
}
public static void main(String[] args) throws Exception {
if (args.length != 2) {
System.err.println("Usage: DatabaseReader geoip2-file.mmdb ip");
System.exit(1);
}
File f = new File(args[0]);
Builder b = new Builder(f);
b.withCache(new CHMCache(256));
DatabaseReader r = b.build();
System.out.println("Database Metadata: " + r.getMetadata());
String c = r.country(args[1]);
System.out.println("IP: " + args[1] + " country: " + c);
}
}