import static java.util.logging.Logger.getLogger;
import static net.pterodactylus.sone.freenet.Key.routingKey;
+import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Collections;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
+import javax.annotation.Nonnull;
+
import net.pterodactylus.sone.core.event.ImageInsertAbortedEvent;
import net.pterodactylus.sone.core.event.ImageInsertFailedEvent;
import net.pterodactylus.sone.core.event.ImageInsertFinishedEvent;
import com.google.inject.Singleton;
import freenet.client.ClientMetadata;
+import freenet.client.FetchContext;
import freenet.client.FetchException;
import freenet.client.FetchException.FetchExceptionMode;
import freenet.client.FetchResult;
import freenet.client.InsertException;
import freenet.client.async.BaseClientPutter;
import freenet.client.async.ClientContext;
+import freenet.client.async.ClientGetCallback;
+import freenet.client.async.ClientGetter;
import freenet.client.async.ClientPutCallback;
import freenet.client.async.ClientPutter;
import freenet.client.async.USKCallback;
private final Map<FreenetURI, USKCallback> uriUskCallbacks = Collections.synchronizedMap(new HashMap<FreenetURI, USKCallback>());
private final RequestClient imageInserts = new RequestClientBuilder().realTime().build();
+ private final RequestClient imageLoader = new RequestClientBuilder().realTime().build();
/**
* Creates a new Freenet interface.
}
}
+ public void startFetch(final FreenetURI uri, final BackgroundFetchCallback backgroundFetchCallback) {
+ ClientGetCallback callback = new ClientGetCallback() {
+ @Override
+ public void onSuccess(FetchResult result, ClientGetter state) {
+ try {
+ backgroundFetchCallback.loaded(uri, result.getMimeType(), result.asByteArray());
+ } catch (IOException e) {
+ backgroundFetchCallback.failed(uri);
+ }
+ }
+
+ @Override
+ public void onFailure(FetchException e, ClientGetter state) {
+ backgroundFetchCallback.failed(uri);
+ }
+
+ @Override
+ public void onResume(ClientContext context) throws ResumeFailedException {
+ /* do nothing. */
+ }
+
+ @Override
+ public RequestClient getRequestClient() {
+ return imageLoader;
+ }
+ };
+ FetchContext fetchContext = client.getFetchContext();
+ try {
+ client.fetch(uri, 1048576, callback, fetchContext, RequestStarter.INTERACTIVE_PRIORITY_CLASS);
+ } catch (FetchException fe) {
+ /* stupid exception that can not actually be thrown! */
+ }
+ }
+
+ public interface BackgroundFetchCallback {
+ void loaded(@Nonnull FreenetURI uri, @Nonnull String mimeType, @Nonnull byte[] data);
+ void failed(@Nonnull FreenetURI uri);
+ }
+
/**
* Inserts the image data of the given {@link TemporaryImage} and returns
* the given insert token that can be used to add listeners or cancel the
package net.pterodactylus.sone.core;
+import static freenet.client.FetchException.FetchExceptionMode.ALL_DATA_NOT_FOUND;
import static freenet.keys.InsertableClientSSK.createRandom;
import static freenet.node.RequestStarter.INTERACTIVE_PRIORITY_CLASS;
import static freenet.node.RequestStarter.PREFETCH_PRIORITY_CLASS;
import static org.mockito.ArgumentCaptor.forClass;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyShort;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.withSettings;
import java.util.HashMap;
import net.pterodactylus.sone.TestUtil;
+import net.pterodactylus.sone.core.FreenetInterface.BackgroundFetchCallback;
import net.pterodactylus.sone.core.FreenetInterface.Callback;
import net.pterodactylus.sone.core.FreenetInterface.Fetched;
import net.pterodactylus.sone.core.FreenetInterface.InsertToken;
import net.pterodactylus.sone.data.TemporaryImage;
import freenet.client.ClientMetadata;
+import freenet.client.FetchContext;
import freenet.client.FetchException;
import freenet.client.FetchException.FetchExceptionMode;
import freenet.client.FetchResult;
import freenet.client.InsertContext;
import freenet.client.InsertException;
import freenet.client.InsertException.InsertExceptionMode;
+import freenet.client.async.ClientGetCallback;
+import freenet.client.async.ClientGetter;
import freenet.client.async.ClientPutter;
import freenet.client.async.USKCallback;
import freenet.client.async.USKManager;
private final Image image = mock(Image.class);
private InsertToken insertToken;
private final Bucket bucket = mock(Bucket.class);
+ private final ArgumentCaptor<ClientGetCallback> clientGetCallback = forClass(ClientGetCallback.class);
+ private final FreenetURI uri = new FreenetURI("KSK@pgl.png");
+ private final FetchResult fetchResult = mock(FetchResult.class);
+ private final BackgroundFetchCallback backgroundFetchCallback = mock(BackgroundFetchCallback.class);
+
+ public FreenetInterfaceTest() throws MalformedURLException {
+ }
+
+ @Before
+ public void setupHighLevelSimpleClient() {
+ when(highLevelSimpleClient.getFetchContext()).thenReturn(mock(FetchContext.class));
+ }
@Before
public void setupFreenetInterface() {
@Test
public void fetchReturnsNullOnFetchExceptions() throws MalformedURLException, FetchException {
FreenetURI freenetUri = new FreenetURI("KSK@GPLv2.txt");
- FetchException fetchException = new FetchException(FetchExceptionMode.ALL_DATA_NOT_FOUND);
+ FetchException fetchException = new FetchException(ALL_DATA_NOT_FOUND);
when(highLevelSimpleClient.fetch(freenetUri)).thenThrow(fetchException);
Fetched fetched = freenetInterface.fetchUri(freenetUri);
assertThat(fetched, nullValue());
assertThat(insertTokenSupplier.apply(image), notNullValue());
}
+ @Test
+ public void backgroundFetchCanBeStarted() throws Exception {
+ freenetInterface.startFetch(uri, backgroundFetchCallback);
+ verify(highLevelSimpleClient).fetch(eq(uri), anyLong(), any(ClientGetCallback.class), any(FetchContext.class), anyShort());
+ }
+
+ @Test
+ public void callbackOfBackgroundFetchIsNotifiedOnSuccess() throws Exception {
+ freenetInterface.startFetch(uri, backgroundFetchCallback);
+ verify(highLevelSimpleClient).fetch(eq(uri), anyLong(), clientGetCallback.capture(), any(FetchContext.class), anyShort());
+ when(fetchResult.getMimeType()).thenReturn("image/png");
+ when(fetchResult.asByteArray()).thenReturn(new byte[] { 1, 2, 3, 4, 5 });
+ clientGetCallback.getValue().onSuccess(fetchResult, mock(ClientGetter.class));
+ verify(backgroundFetchCallback).loaded(uri, "image/png", new byte[] { 1, 2, 3, 4, 5 });
+ verifyNoMoreInteractions(backgroundFetchCallback);
+ }
+
+ @Test
+ public void callbackOfBackgroundFetchIsNotifiedOnFailure() throws Exception {
+ freenetInterface.startFetch(uri, backgroundFetchCallback);
+ verify(highLevelSimpleClient).fetch(eq(uri), anyLong(), clientGetCallback.capture(), any(FetchContext.class), anyShort());
+ when(fetchResult.getMimeType()).thenReturn("image/png");
+ when(fetchResult.asByteArray()).thenReturn(new byte[] { 1, 2, 3, 4, 5 });
+ clientGetCallback.getValue().onFailure(new FetchException(ALL_DATA_NOT_FOUND), mock(ClientGetter.class));
+ verify(backgroundFetchCallback).failed(uri);
+ verifyNoMoreInteractions(backgroundFetchCallback);
+ }
+
+ @Test
+ public void callbackOfBackgroundFetchIsNotifiedAsFailureIfBucketCanNotBeLoaded() throws Exception {
+ freenetInterface.startFetch(uri, backgroundFetchCallback);
+ verify(highLevelSimpleClient).fetch(eq(uri), anyLong(), clientGetCallback.capture(), any(FetchContext.class), anyShort());
+ when(fetchResult.getMimeType()).thenReturn("image/png");
+ when(fetchResult.asByteArray()).thenThrow(IOException.class);
+ clientGetCallback.getValue().onSuccess(fetchResult, mock(ClientGetter.class));
+ verify(backgroundFetchCallback).failed(uri);
+ verifyNoMoreInteractions(backgroundFetchCallback);
+ }
+
}