+ logger.log(FINE, format("Could not unsubscribe USK “%s”!", TO_FREENET_URI.apply(sone)), mue1);
+ }
+ }
+
+ /**
+ * Registers an arbitrary URI and calls the given callback if a new edition
+ * is found.
+ *
+ * @param uri
+ * The URI to watch
+ * @param callback
+ * The callback to call
+ */
+ public void registerUsk(FreenetURI uri, final Callback callback) {
+ USKCallback uskCallback = new CallbackWrapper(callback);
+ try {
+ uskManager.subscribe(USK.create(uri), uskCallback, true, requestClient);
+ uriUskCallbacks.put(uri, uskCallback);
+ } catch (MalformedURLException mue1) {
+ logger.log(WARNING, format("Could not subscribe to USK: %s", uri), mue1);
+ }
+ }
+
+ /**
+ * Unregisters the USK watcher for the given URI.
+ *
+ * @param uri
+ * The URI to unregister the USK watcher for
+ */
+ public void unregisterUsk(FreenetURI uri) {
+ USKCallback uskCallback = uriUskCallbacks.remove(uri);
+ if (uskCallback == null) {
+ logger.log(INFO, format("Could not unregister unknown USK: %s", uri));
+ return;
+ }
+ try {
+ uskManager.unsubscribe(USK.create(uri), uskCallback);
+ } catch (MalformedURLException mue1) {
+ logger.log(INFO, format("Could not unregister invalid USK: %s", uri), mue1);
+ }
+ }
+
+ /**
+ * Container for a fetched URI and the {@link FetchResult}.
+ *
+ * @author <a href="mailto:d.roden@xplosion.de">David Roden</a>
+ */
+ public static class Fetched {
+
+ /** The fetched URI. */
+ private final FreenetURI freenetUri;
+
+ /** The fetch result. */
+ private final FetchResult fetchResult;
+
+ /**
+ * Creates a new fetched URI.
+ *
+ * @param freenetUri
+ * The URI that was fetched
+ * @param fetchResult
+ * The fetch result
+ */
+ public Fetched(FreenetURI freenetUri, FetchResult fetchResult) {
+ this.freenetUri = freenetUri;
+ this.fetchResult = fetchResult;
+ }
+
+ //
+ // ACCESSORS
+ //
+
+ /**
+ * Returns the fetched URI.
+ *
+ * @return The fetched URI
+ */
+ public FreenetURI getFreenetUri() {
+ return freenetUri;
+ }
+
+ /**
+ * Returns the fetch result.
+ *
+ * @return The fetch result
+ */
+ public FetchResult getFetchResult() {
+ return fetchResult;
+ }
+
+ }
+
+ /**
+ * Callback for USK watcher events.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+ public interface Callback {
+
+ /**
+ * Notifies a listener that a new edition was found for a URI.
+ *
+ * @param uri
+ * The URI that a new edition was found for
+ * @param edition
+ * The found edition
+ * @param newKnownGood
+ * Whether the found edition was actually fetched
+ * @param newSlot
+ * Whether the found edition is higher than all previously
+ * found editions
+ */
+ public void editionFound(FreenetURI uri, long edition, boolean newKnownGood, boolean newSlot);
+
+ }
+
+ private static class NewEditionFound implements USKCallback {
+
+ private final Sone sone;
+ private final SoneDownloader soneDownloader;
+
+ public NewEditionFound(Sone sone, SoneDownloader soneDownloader) {
+ this.sone = sone;
+ this.soneDownloader = soneDownloader;
+ }
+
+ @Override
+ @SuppressWarnings("synthetic-access")
+ public void onFoundEdition(long edition, USK key, ObjectContainer objectContainer, ClientContext clientContext, boolean metadata, short codec, byte[] data, boolean newKnownGood, boolean newSlotToo) {
+ logger.log(FINE, format("Found USK update for Sone “%s” at %s, new known good: %s, new slot too: %s.", sone, key, newKnownGood, newSlotToo));
+ if (edition > sone.getLatestEdition()) {
+ sone.modify().setLatestEdition(edition).update();
+ new Thread(new Runnable() {
+
+ @Override
+ public void run() {
+ soneDownloader.fetchSone(sone);
+ }
+ }, format("Sone Downloader for %s", sone.getId())).start();
+ }