package net.i2p.router.time;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import net.i2p.I2PAppContext;
import net.i2p.data.DataHelper;
import net.i2p.router.transport.GeoIP;
/**
* Country to continent mapping for NTP.
* @since 0.9.20
*/
class Zones {
private final I2PAppContext _context;
// can't log here, called from RouterClock constructor, stack overflow
//private final Log _log;
// lower case country to NTP region
private final Map<String, String> _countryToZone;
// upper case continent to NTP region
private final Map<String, String> _continentToZone;
private static final String CONTINENT_FILE_DEFAULT = "continents.txt";
/**
* ref: http://dev.maxmind.com/geoip/legacy/codes/country_continent/
* ref: http://www.pool.ntp.org/zone/@
*/
private static final String[] ZONES = {
// not an NTP zone
//"--", "anonymous-proxy",
"AF", "africa",
// not an NTP zone
//"AN", "antarctica",
"AS", "asia",
"EU", "europe",
"NA", "north-america",
"OC", "oceania",
"SA", "south-america"
};
/**
* Reads in the file in the constructor,
* so hold onto this.
*/
public Zones(I2PAppContext ctx) {
_context = ctx;
//_log = ctx.logManager().getLog(Zones.class);
_countryToZone = new HashMap<String, String>(256);
_continentToZone = new HashMap<String, String>(8);
for (int i = 0; i < ZONES.length; i += 2) {
_continentToZone.put(ZONES[i], ZONES[i+1]);
}
readContinentFile();
}
/**
* Get the NTP zone for a country
*
* @param country non-null, two letter code, case-independent
* @return lower-case NTP zone, e.g. "africa", or null
*/
public String getZone (String country) {
return _countryToZone.get(country.toLowerCase(Locale.US));
}
/**
* Read in and parse the continent file.
* The file need not be sorted.
*
* Format:
* #comment (# must be in column 1)
* country code,continent code
*
* Example:
* US,NA
*
* Modified from GeoIP.readCountryFile()
* ref: http://dev.maxmind.com/geoip/legacy/codes/country_continent/
*/
private void readContinentFile() {
String geoDir = _context.getProperty(GeoIP.PROP_GEOIP_DIR, GeoIP.GEOIP_DIR_DEFAULT);
File geoFile = new File(geoDir);
if (!geoFile.isAbsolute())
geoFile = new File(_context.getBaseDir(), geoDir);
geoFile = new File(geoFile, CONTINENT_FILE_DEFAULT);
if (!geoFile.exists()) {
//if (_log.shouldWarn())
// _log.warn("Continent file not found: " + geoFile.getAbsolutePath());
return;
}
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(
new FileInputStream(geoFile), "UTF-8"));
String line = null;
while ((line = br.readLine()) != null) {
try {
if (line.charAt(0) == '#')
continue;
String[] s = DataHelper.split(line, ",");
String ucContinent = s[1].toUpperCase(Locale.US).trim();
String zone = _continentToZone.get(ucContinent);
if (zone == null)
continue;
String lcCountry = s[0].toLowerCase(Locale.US).trim();
_countryToZone.put(lcCountry, zone);
//if (_log.shouldDebug())
// _log.debug("Country " + lcCountry + " is in " + zone);
} catch (IndexOutOfBoundsException ioobe) {}
}
} catch (IOException ioe) {
System.out.println("Error reading the continent file " + geoFile.getAbsolutePath());
} finally {
if (br != null) try { br.close(); } catch (IOException ioe) {}
}
}
/****
public static void main(String args[]) {
Zones z = new Zones(I2PAppContext.getGlobalContext());
String tests[] = {"us", "US", "nz", "fr", "vU", "br", "cn", "ao", "A1", "foo" };
for (int i = 0; i < tests.length; i++) {
System.out.println(tests[i] + " : " + z.getZone(tests[i]));
}
}
****/
}