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

jadex.base.relay.GeoIPService Maven / Gradle / Ivy

package jadex.base.relay;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.zip.GZIPInputStream;

import com.maxmind.geoip.Location;
import com.maxmind.geoip.LookupService;
import com.maxmind.geoip.regionName;

import jadex.platform.service.message.transport.httprelaymtp.RelayConnectionManager;

/**
 *  Helper object to resolve IP addresses to Geo locations.
 *  Uses free API and database file available at: http://www.maxmind.com/app/geolitecity
 *  Downloads GeoLiteCity.dat into /.relaystats directory.
 */
public class GeoIPService
{
	//-------- static part --------

	/** The singleton db object. */
	protected static final GeoIPService	singleton	= new GeoIPService();
	
	/**
	 *  Get the db instance.
	 */
	public static GeoIPService	getGeoIPService()
	{
		return singleton;
	}
	
	//-------- attributes --------
	
	/** The lookup service (if any). */
	protected LookupService	ls;
	
	/** The date of the last update check. */
	protected long	lastupdate;
	
	//-------- methods --------
	
	/**
	 *  Fetch location name for an IP address.
	 */
	public String	getLocation(String ip)
	{
		updateDB();
		String	ret	= null;
		
		if(ls!=null)
		{
			try
			{
				Location	loc	= ls.getLocation(ip);
				if(loc!=null)
				{
					ret	= loc.city;
					
					String	reg	= regionName.regionNameByCode(loc.countryCode, loc.region);
					if(ret==null)
					{
						ret	= reg;
					}
					else if(!ret.equals(reg))
					{
						ret	+= ", "+reg;
					}
					
					if(ret==null)
					{
						ret	= loc.countryName;
					}
					else if(loc.countryName!=null && !loc.countryName.equals(loc.city) && !loc.countryName.equals(reg))
					{
						ret	+= ", "+loc.countryName;
					}
				}
			}
			catch(Exception e)
			{
				// Ignore errors and let relay work without stats.
				RelayHandler.getLogger().warning("Warning: Could not get Geo location: "+ e);
			}
		}
		
		if(ret==null)
		{
			ret	= "unknown";
		}
		
		return ret;
	}

	/**
	 *  Fetch country code for an IP address or null, if not found.
	 */
	public String	getCountryCode(String ip)
	{
		updateDB();
		String	ret	= null;
		
		if(ls!=null)
		{
			try
			{
				Location	loc	= ls.getLocation(ip);
				if(loc!=null)
				{
					ret	= loc.countryCode.toLowerCase();
				}
			}
			catch(Exception e)
			{
				// Ignore errors and let relay work without stats.
				RelayHandler.getLogger().warning("Warning: Could not get Geo location: "+ e);
			}
		}
		
		return ret;
	}

	/**
	 *  Get the position as latitude,longitude.
	 */
	public String	getPosition(String ip)
	{
		updateDB();
		String	ret	= null;
		
		if(ls!=null)
		{
			try
			{
				Location	loc	= ls.getLocation(ip);
				if(loc!=null)
				{
					ret	= loc.latitude+","+loc.longitude;
				}
			}
			catch(Exception e)
			{
				// Ignore errors and let relay work without stats.
				RelayHandler.getLogger().warning("Warning: Could not get Geo location: "+ e);
			}
		}
		
		return ret;
	}
	
	/**
	 *  Download / check for updates of the GeoIP database.
	 */
	public void	updateDB()
	{
		// Check every 12 hours
		long	update	= System.currentTimeMillis(); 
		if(update-lastupdate>12*60*60*1000)
		{
			synchronized(this)
			{
				if(update-lastupdate>12*60*60*1000)
				{
					lastupdate	= update;
					
					File	dbfile	= new File(RelayHandler.SYSTEMDIR, "GeoLiteCity.dat");
					
					try
					{
						URL	url	= new URL("http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz");
						HttpURLConnection	con	= (HttpURLConnection)url.openConnection();
						if(con.getLastModified()>dbfile.lastModified())	// 0 for non-existant file
						{
							// Close lookup service before updating the database.
							if(ls!=null)
							{
								ls.close();
								ls	= null;
							}
							
							File	tmpfile	= new File(dbfile.getParentFile(), "GeoLiteCity.dat.tmp");
							InputStream	is	= new GZIPInputStream(con.getInputStream());
							OutputStream	os	= new FileOutputStream(tmpfile);
							byte[]	buf	= new byte[8192];
							int read;
							while((read=is.read(buf))!=-1)
							{
								os.write(buf, 0, read);
							}
							os.close();
							is.close();
							if(dbfile.exists())
							{
								// Keep last version, if there are problems with new version.
								File	oldfile	= new File(dbfile.getParentFile(), "GeoLiteCity.dat.old");
								if(oldfile.exists())
								{
									if(!oldfile.delete())
									{
										RelayHandler.getLogger().info("Cannot delete GeoIP database: "+oldfile);
									}
								}
								if(!dbfile.renameTo(oldfile))
								{
									RelayHandler.getLogger().info("Cannot rename old GeoIP database to: "+oldfile);
								}
							}
							if(!tmpfile.renameTo(dbfile))
							{
								RelayHandler.getLogger().info("Cannot rename GeoIP database to: "+dbfile);
							}
							else
							{
								RelayHandler.getLogger().info("Downloaded GeoIP database to: "+dbfile);
							}
						}
					}
					catch(Exception e)
					{
						RelayHandler.getLogger().warning("Warning: Relay could not access GeoIP database: "+ e);
					}

					if(ls==null)
					{
						try
						{
							// Set up geo ip lookup service.
							RelayHandler.getLogger().info("Using GeoIP database from: "+dbfile);
						    ls	= new LookupService(dbfile.getAbsolutePath(), LookupService.GEOIP_MEMORY_CACHE);
						}
						catch(Exception e)
						{
							// Ignore errors and let relay work without geo location.
							RelayHandler.getLogger().warning("Warning: Relay could not initialize GeoIP service: "+ e);
						}
					}
				}
			}
		}
	}
	
	public static void	main(String[] args) throws MalformedURLException
	{
		String	address	= "relay-http://www2.activecomponents.org/relay";
		String	host	= new URL(RelayConnectionManager.httpAddress(address)).getHost();
		System.out.println(host+": "+getGeoIPService().getLocation(host));
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy