All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.tornaia.geoip.GeoIPNonResidentImpl Maven / Gradle / Ivy

There is a newer version: 0.1.12
Show newest version
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.Optional;

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 GeoIPNonResidentImpl implements GeoIP {

    @Override
    public Optional getTwoLetterCountryCode(InetAddress inetAddress) {
        return getTwoLetterCountryCode(inetAddress.getHostAddress());
    }

    @Override
    public Optional getTwoLetterCountryCode(String ipAddress) {
        Optional optionalCountryCodeFromIpv4 = getCountryCodeFromIpv4(ipAddress);
        if (optionalCountryCodeFromIpv4.isPresent()) {
            return optionalCountryCodeFromIpv4;
        }

        return getCountryCodeFromIpv6(ipAddress);
    }

    @Override
    public Optional getCountryName(InetAddress inetAddress) {
        return getCountryName(inetAddress.getHostAddress());
    }

    @Override
    public Optional getCountryName(String ipAddress) {
        Optional optionalCountryNameFromIpv4 = getCountryNameFromIpv4(ipAddress);
        if (optionalCountryNameFromIpv4.isPresent()) {
            return optionalCountryNameFromIpv4;
        }

        return getCountryNameFromIpv6(ipAddress);
    }

    private Optional getCountryCodeFromIpv4(String ipAddress) {
        return findCountryCodeInCsv("GeoLite2-Country-Blocks-IPv4.csv", ipAddress);
    }

    private Optional getCountryNameFromIpv4(String ipAddress) {
        return findCountryNameInCsv("GeoLite2-Country-Blocks-IPv4.csv", ipAddress);
    }

    private Optional getCountryCodeFromIpv6(String ipAddress) {
        return findCountryCodeInCsv("GeoLite2-Country-Blocks-IPv6.csv", ipAddress);
    }

    private Optional getCountryNameFromIpv6(String ipAddress) {
        return findCountryNameInCsv("GeoLite2-Country-Blocks-IPv6.csv", ipAddress);
    }

    private Optional findCountryCodeInCsv(String filename, String ipAddress) {
        try (InputStream is = getClass().getClassLoader().getResourceAsStream(filename)) {
            BufferedReader reader = new BufferedReader(new InputStreamReader(is));
            return reader
                    .lines()
                    .parallel()
                    .skip(1)
                    .map(e -> e.split(","))
                    .filter(e -> !e[IPV_CSV_REGISTERED_COUNTRY_GEONAME_ID].isEmpty() || !e[IPV_CSV_GEONAME_ID].isEmpty())
                    .filter(e -> new IpAddressMatcher(e[LOCATIONS_CSV_GEO_ID]).matches(ipAddress))
                    .map(this::mapCountryCodeToCountryIsoCode)
                    .filter(e -> !e.isEmpty())
                    .findFirst();
        } catch (IOException e) {
            throw new GeoIPException("Failed to read csv: " + filename, e);
        }
    }

    private Optional findCountryNameInCsv(String filename, String ipAddress) {
        try (InputStream is = getClass().getClassLoader().getResourceAsStream(filename)) {
            BufferedReader reader = new BufferedReader(new InputStreamReader(is));
            return reader
                    .lines()
                    .parallel()
                    .skip(1)
                    .map(e -> e.split(","))
                    .filter(e -> !e[IPV_CSV_REGISTERED_COUNTRY_GEONAME_ID].isEmpty() || !e[IPV_CSV_GEONAME_ID].isEmpty())
                    .filter(e -> new IpAddressMatcher(e[LOCATIONS_CSV_GEO_ID]).matches(ipAddress))
                    .map(this::mapCountryCodeToCountryName)
                    .filter(e -> !e.isEmpty())
                    .findFirst();
        } catch (IOException e) {
            throw new GeoIPException("Failed to read csv: " + filename, e);
        }
    }

    private String mapCountryCodeToCountryIsoCode(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(countryId);
    }

    private String mapCountryCodeToCountryName(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 getCountryNameFromCountryId(countryId);
    }

    private String getCountryIsoCodeFromCountryId(String countryId) {
        try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("GeoLite2-Country-Locations-en.csv")) {
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
            return reader
                    .lines()
                    .parallel()
                    .skip(1)
                    .map(e -> e.split(","))
                    .filter(e -> e[LOCATIONS_CSV_GEO_ID].equals(countryId))
                    .map(e -> e[LOCATIONS_CSV_COUNTRY_CODE_ISO])
                    .findFirst()
                    .orElseThrow(() -> new GeoIPException("Country iso code was not found for countryId, countryId: " + countryId));
        } catch (IOException e) {
            throw new GeoIPException("Failed to read GeoLite2-Country-Locations-en.csv", e);
        }
    }

    private String getCountryNameFromCountryId(String countryId) {
        try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("GeoLite2-Country-Locations-en.csv")) {
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
            return reader
                    .lines()
                    .parallel()
                    .skip(1)
                    .map(e -> e.split(","))
                    .filter(e -> e[LOCATIONS_CSV_GEO_ID].equals(countryId))
                    .map(e -> e[LOCATIONS_CSV_COUNTRY_NAME])
                    .map(this::stripLeadingAndTrailingDoubleQuotes)
                    .findFirst()
                    .orElseThrow(() -> new GeoIPException("Country name was not found for countryId, countryId: " + countryId));
        } catch (IOException e) {
            throw new GeoIPException("Failed to read GeoLite2-Country-Locations-en.csv", e);
        }
    }

    private 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;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy