package com.limegroup.gnutella.http; import java.io.IOException; import org.apache.http.Header; import org.apache.http.HttpException; import org.apache.http.HttpRequest; import org.apache.http.protocol.HttpContext; import org.limewire.collection.Function; import org.limewire.http.HeaderInterceptor; import com.limegroup.gnutella.altlocs.AltLocManager; import com.limegroup.gnutella.altlocs.AltLocUtils; import com.limegroup.gnutella.altlocs.AlternateLocation; import com.limegroup.gnutella.altlocs.AlternateLocationFactory; import com.limegroup.gnutella.altlocs.PushAltLoc; import com.limegroup.gnutella.uploader.HTTPUploader; /** * Processes alternate location headers from an {@link HttpRequest} and updates * a corresponding {@link HTTPUploader}. */ public class AltLocHeaderInterceptor implements HeaderInterceptor { private final HTTPUploader uploader; private final AltLocManager altLocManager; private final AlternateLocationFactory alternateLocationFactory; public AltLocHeaderInterceptor(HTTPUploader uploader, AltLocManager altLocManager, AlternateLocationFactory alternateLocationFactory) { this.uploader = uploader; this.altLocManager = altLocManager; this.alternateLocationFactory = alternateLocationFactory; } public void process(Header header, HttpContext context) throws HttpException, IOException { if (HTTPHeaderName.ALT_LOCATION.matches(header)) { parseAlternateLocations(uploader.getAltLocTracker(), header.getValue(), true, true); } else if (HTTPHeaderName.NALTS.matches(header)) { parseAlternateLocations(uploader.getAltLocTracker(), header.getValue(), false, false); } else if (HTTPHeaderName.FALT_LOCATION.matches(header)) { AltLocTracker tracker = uploader.getAltLocTracker(); parseAlternateLocations(tracker, header.getValue(), true, false); tracker.setWantsFAlts(true); } else if (HTTPHeaderName.BFALT_LOCATION.matches(header)) { AltLocTracker tracker = uploader.getAltLocTracker(); parseAlternateLocations(tracker, header.getValue(), false, false); tracker.setWantsFAlts(false); } } /** * Parses the alternate location header. The header can contain only one * alternate location, or it can contain many in the same header. This * method will notify DownloadManager of new alternate locations if the * FileDesc is an IncompleteFileDesc. * * @param altLocTracker the tracker that stores locations * @param altHeader the full alternate locations header */ private void parseAlternateLocations(final AltLocTracker tracker, String alternateLocations, final boolean isGood, boolean allowTLS) { AltLocUtils.parseAlternateLocations(tracker.getUrn(), alternateLocations, allowTLS, alternateLocationFactory, new Function<AlternateLocation, Void>() { public Void apply(AlternateLocation location) { if (location instanceof PushAltLoc) ((PushAltLoc) location).updateProxies(isGood); // Note: if this thread gets preempted at this point, // the AlternateLocationCollectioin may contain a PE // without any proxies. if (isGood) altLocManager.add(location, null); else altLocManager.remove(location, null); tracker.addLocation(location); return null; } }); } }