package org.limewire.geocode; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Properties; import java.util.concurrent.atomic.AtomicBoolean; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.limewire.geocode.GeocodeInformation.Property; import org.limewire.inject.MutableProvider; import org.limewire.io.NetworkUtils; import org.limewire.net.ExternalIP; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; @Singleton public class CachedGeoLocationImpl implements Provider<GeocodeInformation> { private static final Log LOG = LogFactory.getLog(CachedGeoLocationImpl.class); private final MutableProvider<Properties> geoLocation; private final Provider<Geocoder> geocoder; private volatile GeocodeInformation info; private final Provider<byte[]> externalAddress; private final AtomicBoolean initialized = new AtomicBoolean(false); @Inject public CachedGeoLocationImpl(@GeoLocation MutableProvider<Properties> geoLocation, Provider<Geocoder> geocoder, @ExternalIP Provider<byte []> externalAddress) { this.geoLocation = geoLocation; this.geocoder = geocoder; this.externalAddress = externalAddress; } public GeocodeInformation get() { // Note: if this is called fast enough in succession, // the second call may see null before this is initialized. if (initialized.compareAndSet(false, true)) { LOG.debug("initializing"); initialize(); } return info; } void initialize() { info = GeocodeInformation.fromProperties(geoLocation.get()); if (info != null) { // check if the info is not stale byte[] currentAddress = externalAddress.get(); if (currentAddress == null) { LOG.debug("no address from networkmanager to compare with"); // nothing to compare with return; } String lastAddress = info.getProperty(Property.Ip); if (lastAddress != null) { try { byte[] lastIp = InetAddress.getByName(lastAddress).getAddress(); if (LOG.isDebugEnabled()) { LOG.debug("comparing addressed: " + lastAddress + " and " + NetworkUtils.ip2string(currentAddress)); } if (NetworkUtils.isCloseIP(currentAddress, lastIp)) { return; } } catch (UnknownHostException e) { LOG.warn("Unable to get host by name", e); } } } Geocoder coder = geocoder.get(); coder.initialize(); info = coder.getGeocodeInformation(); if (info != null) { if (LOG.isDebugEnabled()) { LOG.debug("new info: " + info); } geoLocation.set(info.toProperties()); } } }