package org.rakam.collection.mapper.geoip.maxmind.ip2location; import org.rakam.collection.mapper.geoip.maxmind.ip2location.utils.IP4Converter; import java.io.*; import java.math.BigInteger; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Map; import java.util.NavigableMap; import java.util.concurrent.ConcurrentSkipListMap; public class IPReader { private final NavigableMap<Long, CSV> ipLookup; private IPReader(NavigableMap<Long, CSV> ipLookup) { this.ipLookup = ipLookup; } public static IPReader build(String dbPath) throws IOException { File ipdb = new File(dbPath); InputStream inputStream = new FileInputStream(ipdb); return build(inputStream); } public static IPReader build(InputStream inputStream) throws IOException { NavigableMap<Long, CSV> lookup = new ConcurrentSkipListMap<>(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); while (reader.ready()) { CSV csv = CSV.parse(reader.readLine()); lookup.put(csv.ipStart, csv); } reader.close(); return new IPReader(lookup); } public GeoLocation lookup(String ipAddress) throws UnknownHostException { InetAddress inetAddress = InetAddress.getByName(ipAddress); return lookup(inetAddress); } public GeoLocation lookup(InetAddress inetAddress) { return lookup(IP4Converter.toLong(inetAddress.getAddress())); } private GeoLocation lookup(Long address) { Map.Entry<Long, CSV> entry = ipLookup.lowerEntry(address); if (entry == null) { return null; } CSV csv = entry.getValue(); if (csv.ipEnd < address) { return null; } return GeoLocation.of(csv.country, csv.stateProv, csv.city, Coordination.of(csv.latitude, csv.longitude)); } private Long toLong(byte[] address) { return new BigInteger(address).longValue(); } }