Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.covert.dns.geo; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.collections.map.LRUMap; import org.codehaus.jackson.JsonGenerationException; import org.codehaus.jackson.map.JsonMappingException; import com.maxmind.geoip.Location; import com.maxmind.geoip.LookupService; public class IpGeo { private static final String UNKNOWN = "UNKNOWN"; private static Map<String, Object> UNKNOWN_GEO = new HashMap<String, Object>(); private static final String RFC1918 = "RFC1918"; private static Map<String, Object> RFC1918_GEO = new HashMap<String, Object>(); private static final Pattern asnumPattern = Pattern.compile("^AS(\\d+)\\s+(.+)$"); private static final String[] rfc1918Slash8Prefixes = { "10.", "192.", "172." }; private static final String[] rfc1918AddressPrefixes = { "10.", "192.168.", "172.16.", "172.17.", "172.18.", "172.19.", "172.20.", "172.21.", "172.22.", "172.23.", "172.24.", "172.25.", "172.26.", "172.27.", "172.28.", "172.29.", "172.30.", "172.31.", }; static { put(UNKNOWN_GEO, "city", UNKNOWN); put(UNKNOWN_GEO, "cc", UNKNOWN); put(UNKNOWN_GEO, "country", UNKNOWN); put(UNKNOWN_GEO, "lat", 0.0f); put(UNKNOWN_GEO, "long", 0.0f); put(UNKNOWN_GEO, "asn", UNKNOWN); put(UNKNOWN_GEO, "org", UNKNOWN); put(RFC1918_GEO, "city", RFC1918); put(RFC1918_GEO, "cc", RFC1918); put(RFC1918_GEO, "country", RFC1918); put(RFC1918_GEO, "lat", 0.0f); put(RFC1918_GEO, "long", 0.0f); put(RFC1918_GEO, "asn", RFC1918); put(RFC1918_GEO, "org", RFC1918); } LookupService maxmind; LookupService asnLookup; LRUMap lru = new LRUMap(10000); public IpGeo(String dbFile, int options) throws IOException { maxmind = new LookupService(dbFile, LookupService.GEOIP_MEMORY_CACHE); } public IpGeo(String locationDbFile, String asnDbFile, int options) throws IOException { maxmind = new LookupService(locationDbFile, options); asnLookup = new LookupService(asnDbFile, options); } public Map<String, Object> getLocation(String ip) throws JsonGenerationException, JsonMappingException, IOException { for (String prefix : rfc1918Slash8Prefixes) { if (ip.startsWith(prefix)) { for (String addrPrefix : rfc1918AddressPrefixes) { if (ip.startsWith(addrPrefix)) return RFC1918_GEO; } break; } } Object val = lru.get(ip); if (val != null) return (Map<String, Object>) val; Location loc = maxmind.getLocation(ip); if (loc == null) { lru.put(ip, UNKNOWN_GEO); return UNKNOWN_GEO; } Map<String, Object> rec = new HashMap<String, Object>(); put(rec, "city", loc.city); put(rec, "cc", loc.countryCode); put(rec, "country", loc.countryName); put(rec, "lat", loc.latitude); put(rec, "long", loc.longitude); if (asnLookup != null) { String org = asnLookup.getOrg(ip); if (org != null) { Matcher mat = asnumPattern.matcher(org); if (mat.matches()) { put(rec, "asn", mat.group(1)); put(rec, "org", mat.group(2)); } else { put(rec, "org", org); } } } lru.put(ip, rec); return rec; } private static void put(Map<String, Object> rec, String name, Object val) { if (val != null) rec.put(name, val.toString().toUpperCase()); } public void close() { lru.clear(); maxmind.close(); if (asnLookup != null) { asnLookup.close(); } } }