com.github.tornaia.geoip.GeoIPResidentImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of java-offline-geoip Show documentation
Show all versions of java-offline-geoip Show documentation
Java Offline GeoIP maps any IP address to its country code
package com.github.tornaia.geoip;
import com.github.tornaia.geoip.internal.IpAddressMatcher;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import static com.github.tornaia.geoip.GeoLiteConstants.IPV_CSV_GEONAME_ID;
import static com.github.tornaia.geoip.GeoLiteConstants.IPV_CSV_REGISTERED_COUNTRY_GEONAME_ID;
import static com.github.tornaia.geoip.GeoLiteConstants.LOCATIONS_CSV_COUNTRY_CODE_ISO;
import static com.github.tornaia.geoip.GeoLiteConstants.LOCATIONS_CSV_COUNTRY_NAME;
import static com.github.tornaia.geoip.GeoLiteConstants.LOCATIONS_CSV_GEO_ID;
public class GeoIPResidentImpl implements GeoIP {
private static class MapHolder {
private static final Map CIDR_NOTATIONS_TO_COUNTRY_ISO_CODE_MAP = getCidrNotationsToCountryIdoCodeMap();
private static final Map COUNTRY_ISO_CODE_TO_COUNTRY_NAME_MAP = getCountryIsoCodeToCountryNameMapInternal();
private static Map getCidrNotationsToCountryIdoCodeMap() {
Map cidrNotationsToCountryIsoCodeMap = new HashMap<>();
Map countryIdToCountryIsoCodeMap = getCountryIdToCountryIsoCodeMap();
loadIpv4Csv(cidrNotationsToCountryIsoCodeMap, countryIdToCountryIsoCodeMap);
loadIpv6Csv(cidrNotationsToCountryIsoCodeMap, countryIdToCountryIsoCodeMap);
return cidrNotationsToCountryIsoCodeMap;
}
private static void loadIpv4Csv(Map cidrNotationsToCountryIsoCodeMap, Map countryIdToCountryIsoCodeMap) {
loadIpvCsv(cidrNotationsToCountryIsoCodeMap, countryIdToCountryIsoCodeMap, "GeoLite2-Country-Blocks-IPv4.csv");
}
private static void loadIpv6Csv(Map cidrNotationsToCountryIsoCodeMap, Map countryIdToCountryIsoCodeMap) {
loadIpvCsv(cidrNotationsToCountryIsoCodeMap, countryIdToCountryIsoCodeMap, "GeoLite2-Country-Blocks-IPv6.csv");
}
private static void loadIpvCsv(Map cidrNotationsToCountryIsoCodeMap, Map countryIdToCountryIsoCodeMap, String filename) {
try (InputStream inputStream = MapHolder.class.getClassLoader().getResourceAsStream(filename)) {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
Map ipMap = reader
.lines()
.skip(1)
.map(e -> e.split(","))
.filter(e -> !e[IPV_CSV_REGISTERED_COUNTRY_GEONAME_ID].isEmpty() || !e[IPV_CSV_GEONAME_ID].isEmpty())
.collect(Collectors.toMap(e -> new IpAddressMatcher(e[LOCATIONS_CSV_GEO_ID]), e -> mapCountryCodeToCountryIsoCode(countryIdToCountryIsoCodeMap, e)));
cidrNotationsToCountryIsoCodeMap.putAll(ipMap);
} catch (IOException e) {
throw new GeoIPException("Failed to read csv: " + filename, e);
}
}
private static Map getCountryIdToCountryIsoCodeMap() {
try (InputStream inputStream = MapHolder.class.getClassLoader().getResourceAsStream("GeoLite2-Country-Locations-en.csv")) {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
return reader
.lines()
.skip(1)
.map(e -> e.split(","))
.collect(Collectors.toMap(e -> e[LOCATIONS_CSV_GEO_ID], e -> e[LOCATIONS_CSV_COUNTRY_CODE_ISO]));
} catch (IOException e) {
throw new GeoIPException("Failed to read GeoLite2-Country-Locations-en.csv", e);
}
}
private static Map getCountryIsoCodeToCountryNameMapInternal() {
try (InputStream inputStream = MapHolder.class.getClassLoader().getResourceAsStream("GeoLite2-Country-Locations-en.csv")) {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
return reader
.lines()
.skip(1)
.map(e -> e.split(","))
.filter(e -> e[LOCATIONS_CSV_COUNTRY_CODE_ISO] != null && !e[LOCATIONS_CSV_COUNTRY_CODE_ISO].isEmpty())
.filter(e -> e[LOCATIONS_CSV_COUNTRY_NAME] != null && !e[LOCATIONS_CSV_COUNTRY_NAME].isEmpty())
.collect(Collectors.toMap(e -> e[LOCATIONS_CSV_COUNTRY_CODE_ISO], e -> stripLeadingAndTrailingDoubleQuotes(e[LOCATIONS_CSV_COUNTRY_NAME]), (a, b) -> a));
} catch (IOException e) {
throw new GeoIPException("Failed to read GeoLite2-Country-Locations-en.csv", e);
}
}
private static String mapCountryCodeToCountryIsoCode(Map countryIdToCountryIsoCodeMap, String[] splittedLine) {
String registeredCountryGeonameId = splittedLine[IPV_CSV_REGISTERED_COUNTRY_GEONAME_ID];
String geonameId = splittedLine[IPV_CSV_GEONAME_ID];
String countryId = registeredCountryGeonameId.isEmpty() ? geonameId : registeredCountryGeonameId;
return getCountryIsoCodeFromCountryId(countryIdToCountryIsoCodeMap, countryId);
}
private static String getCountryIsoCodeFromCountryId(Map countryIdToCountryIsoCodeMap, String countryId) {
String countryIsoCode = countryIdToCountryIsoCodeMap.get(countryId);
boolean countryIsoCodeWasNotFoundForCountryId = countryIsoCode == null;
if (countryIsoCodeWasNotFoundForCountryId) {
throw new GeoIPException("Country iso code was not found for countryId, countryId: " + countryId);
}
return countryIsoCode;
}
private static String stripLeadingAndTrailingDoubleQuotes(String maybeQuotedCountryName) {
String countryName = maybeQuotedCountryName;
if (countryName.startsWith("\"")) {
countryName = countryName.substring(1);
}
if (countryName.endsWith("\"")) {
countryName = countryName.substring(0, countryName.length() - 1);
}
return countryName;
}
private static Map getCidrNotationsToCountryIsoCodeMap() {
return MapHolder.CIDR_NOTATIONS_TO_COUNTRY_ISO_CODE_MAP;
}
private static Map getCountryIsoCodeToCountryNameMap() {
return MapHolder.COUNTRY_ISO_CODE_TO_COUNTRY_NAME_MAP;
}
}
@Override
public Optional getTwoLetterCountryCode(InetAddress inetAddress) {
return getTwoLetterCountryCode(inetAddress.getHostAddress());
}
@Override
public Optional getTwoLetterCountryCode(String ipAddress) {
return MapHolder.getCidrNotationsToCountryIsoCodeMap()
.entrySet()
.parallelStream()
.filter(e -> e.getKey().matches(ipAddress))
.map(Map.Entry::getValue)
.filter(e -> !e.isEmpty())
.findFirst();
}
@Override
public Optional getCountryName(InetAddress inetAddress) {
return getCountryName(inetAddress.getHostAddress());
}
@Override
public Optional getCountryName(String ipAddress) {
Optional optionalTwoLetterCountryCode = getTwoLetterCountryCode(ipAddress);
if (optionalTwoLetterCountryCode.isPresent()) {
String twoLetterCountryCode = optionalTwoLetterCountryCode.get();
Map countryIsoCodeToCountryNameMap = MapHolder.getCountryIsoCodeToCountryNameMap();
String countryName = countryIsoCodeToCountryNameMap.get(twoLetterCountryCode);
return Optional.ofNullable(countryName);
}
return Optional.empty();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy