import java.io.IOException;
import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
+import java.util.function.Consumer;
import java.util.function.Supplier;
import net.pterodactylus.fcp.AllData;
private final ListeningExecutorService threadPool;
private final ConnectionSupplier connectionSupplier;
private final Supplier<String> identifierGenerator;
+ private final List<Consumer<String>> onRedirects = new ArrayList<>();
private boolean ignoreDataStore;
private boolean dataStoreOnly;
}
@Override
+ public ClientGetCommand onRedirect(Consumer<String> onRedirect) {
+ onRedirects.add(onRedirect);
+ return this;
+ }
+
+ @Override
public ClientGetCommand ignoreDataStore() {
ignoreDataStore = true;
return this;
}
private Optional<Data> execute(String uri) throws InterruptedException, ExecutionException, IOException {
- ClientGet clientGet = createClientGetCommand(uri);
+ ClientGet clientGet = createClientGetCommand(identifierGenerator.get(), uri);
try (ClientGetDialog clientGetDialog = new ClientGetDialog()) {
return clientGetDialog.send(clientGet).get();
}
}
- private ClientGet createClientGetCommand(String uri) {
- String identifier = identifierGenerator.get();
+ private ClientGet createClientGetCommand(String identifier, String uri) {
ClientGet clientGet = new ClientGet(uri, identifier, ReturnType.direct);
if (ignoreDataStore) {
clientGet.setIgnoreDataStore(true);
private class ClientGetDialog extends FcpDialog<Optional<Data>> {
public ClientGetDialog() throws IOException {
- super(ClientGetCommandImpl.this.threadPool, ClientGetCommandImpl.this.connectionSupplier.get(), Optional.<Data>empty());
+ super(ClientGetCommandImpl.this.threadPool, ClientGetCommandImpl.this.connectionSupplier.get(),
+ Optional.<Data>empty());
}
@Override
@Override
protected void consumeGetFailed(GetFailed getFailed) {
- finish();
+ if (getFailed.getCode() == 27) {
+ onRedirects.forEach(onRedirect -> onRedirect.accept(getFailed.getRedirectURI()));
+ sendMessage(createClientGetCommand(getIdentifier(), getFailed.getRedirectURI()));
+ } else {
+ finish();
+ }
}
}
connectAndAssert(() -> matchesFcpMessage("ClientGet", "URI=KSK@foo.txt", "Global=true"));
}
+ @Test
+ public void clientGetFollowsRedirect() throws InterruptedException, ExecutionException, IOException {
+ Future<Optional<Data>> data = fcpClient.clientGet().uri("USK@foo/bar").execute();
+ connectAndAssert(() -> matchesFcpMessage("ClientGet", "URI=USK@foo/bar"));
+ replyWithRedirect("USK@foo/baz");
+ readMessage(() -> matchesFcpMessage("ClientGet", "URI=USK@foo/baz"));
+ replyWithAllData(identifier, "Hello", "text/plain;charset=utf-8");
+ verifyData(data.get());
+ }
+
+ @Test
+ public void clientGetNotifiesListenersOnRedirect() throws IOException, ExecutionException, InterruptedException {
+ List<String> redirects = new ArrayList<>();
+ Future<Optional<Data>> data = fcpClient.clientGet().onRedirect(redirects::add).uri("USK@foo/bar").execute();
+ connectAndAssert(() -> matchesFcpMessage("ClientGet", "URI=USK@foo/bar"));
+ replyWithRedirect("USK@foo/baz");
+ readMessage(() -> matchesFcpMessage("ClientGet", "URI=USK@foo/baz"));
+ replyWithRedirect("USK@foo/quux");
+ readMessage(() -> matchesFcpMessage("ClientGet", "URI=USK@foo/quux"));
+ replyWithAllData(identifier, "Hello", "text/plain;charset=utf-8");
+ verifyData(data.get());
+ assertThat(redirects, contains("USK@foo/baz", "USK@foo/quux"));
+ }
+
private void replyWithGetFailed(String identifier) throws IOException {
fcpServer.writeLine(
"GetFailed",
);
}
+ private void replyWithRedirect(String newUri) throws IOException {
+ fcpServer.writeLine(
+ "GetFailed",
+ "Identifier=" + identifier,
+ "Code=27",
+ "RedirectURI=" + newUri,
+ "EndMessage"
+ );
+ }
+
private void replyWithAllData(String identifier, String text, String contentType) throws IOException {
fcpServer.writeLine(
"AllData",