From 3d9879f268ac491cfc7ce8d6e3030f75ff2cdd44 Mon Sep 17 00:00:00 2001 From: =?utf8?q?David=20=E2=80=98Bombe=E2=80=99=20Roden?= Date: Tue, 7 Sep 2010 12:16:14 +0200 Subject: [PATCH] Add method to retrieve a single URI. --- .../net/pterodactylus/fcp/highlevel/FcpClient.java | 71 ++++++- .../net/pterodactylus/fcp/highlevel/GetResult.java | 219 +++++++++++++++++++++ 2 files changed, 289 insertions(+), 1 deletion(-) create mode 100644 src/main/java/net/pterodactylus/fcp/highlevel/GetResult.java diff --git a/src/main/java/net/pterodactylus/fcp/highlevel/FcpClient.java b/src/main/java/net/pterodactylus/fcp/highlevel/FcpClient.java index 91a27f0..dee33c3 100644 --- a/src/main/java/net/pterodactylus/fcp/highlevel/FcpClient.java +++ b/src/main/java/net/pterodactylus/fcp/highlevel/FcpClient.java @@ -28,11 +28,13 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; -import java.util.Set; import java.util.Map.Entry; +import java.util.Set; import java.util.concurrent.CountDownLatch; import net.pterodactylus.fcp.AddPeer; +import net.pterodactylus.fcp.AllData; +import net.pterodactylus.fcp.ClientGet; import net.pterodactylus.fcp.ClientHello; import net.pterodactylus.fcp.CloseConnectionDuplicateClientName; import net.pterodactylus.fcp.DataFound; @@ -67,6 +69,7 @@ import net.pterodactylus.fcp.SimpleProgress; import net.pterodactylus.fcp.WatchGlobal; import net.pterodactylus.util.filter.Filter; import net.pterodactylus.util.filter.Filters; +import net.pterodactylus.util.io.TemporaryInputStream; import net.pterodactylus.util.thread.ObjectWrapper; /** @@ -303,6 +306,72 @@ public class FcpClient { } /** + * Returns the file with the given URI. + * + * @param uri + * The URI to get + * @return The result of the get request + * @throws IOException + * if an I/O error occurs + * @throws FcpException + * if an FCP error occurs + */ + public GetResult getURI(final String uri) throws IOException, FcpException { + checkConnected(true); + final GetResult getResult = new GetResult(); + new ExtendedFcpAdapter() { + + @SuppressWarnings("synthetic-access") + private final String identifier = createIdentifier("client-get"); + + @Override + @SuppressWarnings("synthetic-access") + public void run() throws IOException { + ClientGet clientGet = new ClientGet(uri, identifier); + fcpConnection.sendMessage(clientGet); + } + + @Override + public void receivedGetFailed(FcpConnection fcpConnection, GetFailed getFailed) { + if (!getFailed.getIdentifier().equals(identifier)) { + return; + } + if (getFailed.getCode() == 27) { + /* redirect! */ + String newUri = getFailed.getRedirectURI(); + getResult.realUri(newUri); + try { + fcpConnection.sendMessage(new ClientGet(newUri, identifier)); + } catch (IOException ioe1) { + getResult.success(false).exception(ioe1); + completionLatch.countDown(); + } + } else { + getResult.success(false).errorCode(getFailed.getCode()); + completionLatch.countDown(); + } + } + + @Override + public void receivedAllData(FcpConnection fcpConnection, AllData allData) { + if (!allData.getIdentifier().equals(identifier)) { + return; + } + InputStream temporaryInputStream; + try { + temporaryInputStream = new TemporaryInputStream(allData.getPayloadInputStream()); + getResult.success(true).contentType(allData.getContentType()).contentLength(allData.getDataLength()).inputStream(temporaryInputStream); + } catch (IOException ioe1) { + getResult.success(false).exception(ioe1); + } + completionLatch.countDown(); + } + + }.execute(); + return getResult; + } + + /** * Disconnects the FCP client. */ public void disconnect() { diff --git a/src/main/java/net/pterodactylus/fcp/highlevel/GetResult.java b/src/main/java/net/pterodactylus/fcp/highlevel/GetResult.java new file mode 100644 index 0000000..15bbb8d --- /dev/null +++ b/src/main/java/net/pterodactylus/fcp/highlevel/GetResult.java @@ -0,0 +1,219 @@ +/* + * jFCPlib - GetResult.java - Copyright © 2010 David Roden + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.pterodactylus.fcp.highlevel; + +import java.io.InputStream; +import java.util.EventListener; + +/** + * A get result encapsulates the result of {@link FcpClient#getURI(String)}. It + * is used to allow synchronous retrieval of a file without resorting to + * {@link EventListener} interfaces to notify the application of intermediary + * results, such as redirects. + * + * @author David ‘Bombe’ Roden + */ +public class GetResult { + + /** Whether the request was successful. */ + private boolean success; + + /** The error code, if an error occured. */ + private int errorCode; + + /** The exception, if an exception occured. */ + private Throwable exception; + + /** The real URI, if a redirect was found. */ + private String realUri; + + /** The content type of the file. */ + private String contentType; + + /** The length of the file. */ + private long contentLength; + + /** An input stream containing the data of the file. */ + private InputStream inputStream; + + /** + * Returns whether the request was successful. + * + * @return {@code true} if the request was successful, {@code false} + * otherwise + */ + public boolean isSuccess() { + return success; + } + + /** + * Sets whether the request was successful. + * + * @param success + * {@code true} if the request was successful, {@code false} + * otherwise + * @return This result, to allow method chaning + */ + GetResult success(boolean success) { + this.success = success; + return this; + } + + /** + * Returns the error code of the request. The error code is the error code + * that is transferred in FCP’s “GetFailed” message. The error code is not + * valid if {@link #isSuccess()} is {@code true}. If an exception occured + * (i.e. if {@link #getException()} returns a non-{@code null} value) the + * error code might also be invalid. + * + * @return The error code of the request + */ + public int getErrorCode() { + return errorCode; + } + + /** + * Sets the error code of the request. + * + * @param errorCode + * The error code of the request + * @return This result, to allow method chaining + */ + GetResult errorCode(int errorCode) { + this.errorCode = errorCode; + return this; + } + + /** + * Returns the exception, if any occured. + * + * @return The occured exception, or {@code null} if there was no exception + */ + public Throwable getException() { + return exception; + } + + /** + * Sets the exception that occured. + * + * @param exception + * The occured exception + * @return This result, to allow method chaining + */ + GetResult exception(Throwable exception) { + this.exception = exception; + return this; + } + + /** + * Returns the real URI in case of a redirect. + * + * @return The real URI, or {@code null} if there was no redirect + */ + public String getRealUri() { + return realUri; + } + + /** + * Sets the real URI in case of a redirect. + * + * @param realUri + * The real URI + * @return This result, to allow method chaining + */ + GetResult realUri(String realUri) { + this.realUri = realUri; + return this; + } + + /** + * Returns the content type of the result. + * + * @return The content type of the result + */ + public String getContentType() { + return contentType; + } + + /** + * Sets the content type of the result. + * + * @param contentType + * The content type of the result + * @return This result, to allow method chaining + */ + GetResult contentType(String contentType) { + this.contentType = contentType; + return this; + } + + /** + * Returns the content length of the result. + * + * @return The content length of the result + */ + public long getContentLength() { + return contentLength; + } + + /** + * Sets the content length of the result. + * + * @param contentLength + * The content length of the result + * @return This result, to allow method chaining + */ + GetResult contentLength(long contentLength) { + this.contentLength = contentLength; + return this; + } + + /** + * Returns the data. + * + * @return The data + */ + public InputStream getInputStream() { + return inputStream; + } + + /** + * Sets the input stream that will deliver the data. + * + * @param inputStream + * The input stream containing the data + * @return This result, to allow method chaining + */ + GetResult inputStream(InputStream inputStream) { + this.inputStream = inputStream; + return this; + } + + // + // OBJECT METHODS + // + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + return getClass().getName() + "[success=" + success + ",errorCode=" + errorCode + ",exception=" + exception + ",realUri=" + realUri + ",contentType=" + contentType + ",contentLength=" + contentLength + ",inputStream=" + inputStream + "]"; + } + +} -- 2.7.4