package plugins.CENO.Client;
import java.util.Hashtable;
import plugins.CENO.CENOErrCode;
import plugins.CENO.CENOException;
import plugins.CENO.Common.URLtoUSKTools;
import freenet.client.FetchException;
import freenet.client.FetchException.FetchExceptionMode;
import freenet.client.FetchResult;
import freenet.client.async.ClientContext;
import freenet.client.async.ClientGetCallback;
import freenet.client.async.ClientGetter;
import freenet.keys.FreenetURI;
import freenet.node.RequestClient;
import freenet.support.Logger;
import freenet.support.io.ResumeFailedException;
public class ULPRManager {
private static ULPRManager ulprManager = null;
private Hashtable<String, ULPRStatus> ulprTable;
public enum ULPRStatus {
starting,
inProgress,
succeeded,
failed,
couldNotStart
};
private class ULPRGetCallback implements ClientGetCallback {
private String url;
public ULPRGetCallback(String url) {
this.url = url;
}
public void onSuccess(FetchResult result, ClientGetter state) {
Logger.normal(this, "ULPR completed successfully for URL: " + url);
updateULPRStatus(url, ULPRStatus.succeeded);
RequestSender.getInstance().removeFromBatch(url);
}
public void onFailure(FetchException e, ClientGetter state) {
//TODO Handle not fatal errors (like permanent redirections)
if (e.getMode() == FetchExceptionMode.PERMANENT_REDIRECT) {
try {
initULPR(url, e.newURI.getEdition());
} catch (CENOException e1) {
// Unlikely to happen
e1.printStackTrace();
}
} else {
updateULPRStatus(url, ULPRStatus.failed);
Logger.error(this, "ULPR failed for a url, Exception: " + e.getMessage());
Logger.normal(this, "ULPR failed for url: " + url + " Exception: " + e.getMessage());
}
}
public void onResume(ClientContext context) throws ResumeFailedException {}
public RequestClient getRequestClient() {
return CENOClient.nodeInterface.getRequestClient();
}
}
private ULPRManager() {
this.ulprTable = new Hashtable<String, ULPRManager.ULPRStatus>();
}
public static void init() {
synchronized (ULPRManager.class) {
if (ulprManager == null) {
ulprManager = new ULPRManager();
}
}
}
public static ULPRStatus lookupULPR(String url) throws CENOException {
//TODO Experiment with -1 as suggested edition
return lookupULPR(url, 0);
}
public static ULPRStatus lookupULPR(String url, long suggestedEdition) throws CENOException {
if (!urlExistsInTable(url)) {
ulprManager.initULPR(url, suggestedEdition);
}
return getULPRStatus(url);
}
private static boolean urlExistsInTable(String url) {
return ulprManager.ulprTable.containsKey(url);
}
public static ULPRStatus getULPRStatus(String url) {
return ulprManager.ulprTable.get(url);
}
private static void updateULPRStatus(String url, ULPRStatus status) {
ulprManager.ulprTable.put(url, status);
}
private void initULPR(String url, long newEdition) throws CENOException {
updateULPRStatus(url, ULPRStatus.starting);
FreenetURI calculatedUSK = null;
try {
calculatedUSK = URLtoUSKTools.computeUSKfromURL(url, CENOClient.getBridgeKey());
} catch (Exception e) {
Logger.error(this, "Could not calculate USK for a URL");
Logger.normal(this, "Could not calculate USK for URL: " + url);
updateULPRStatus(url, ULPRStatus.couldNotStart);
throw new CENOException(CENOErrCode.LCS_HANDLER_URL_TO_USK);
}
calculatedUSK = calculatedUSK.setSuggestedEdition(newEdition);
try {
CENOClient.nodeInterface.fetchULPR(calculatedUSK, new ULPRGetCallback(url));
} catch (FetchException e) {
Logger.error(this, "Could not start ULPR for a URL");
Logger.normal(this, "Could not start ULPR for URL: " + url);
updateULPRStatus(url, ULPRStatus.couldNotStart);
throw new CENOException(CENOErrCode.LCS_LOOKUP_ULPR_INIT);
}
updateULPRStatus(url, ULPRStatus.inProgress);
}
}