X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=src%2Fmain%2Fjava%2Fnet%2Fpterodactylus%2Ffcp%2Fhighlevel%2FFcpClient.java;h=7364aa8a01ce58c44b5114c38fb7f1673f9175e7;hb=572802370f7dff98b690df85b79e256335e28b33;hp=a7ccd3ec77059b2f43a664a2c64b7163e5d38eae;hpb=960c723062d160be95e526ac24b7a664e0ac217e;p=jFCPlib.git diff --git a/src/main/java/net/pterodactylus/fcp/highlevel/FcpClient.java b/src/main/java/net/pterodactylus/fcp/highlevel/FcpClient.java index a7ccd3e..7364aa8 100644 --- a/src/main/java/net/pterodactylus/fcp/highlevel/FcpClient.java +++ b/src/main/java/net/pterodactylus/fcp/highlevel/FcpClient.java @@ -18,6 +18,7 @@ package net.pterodactylus.fcp.highlevel; +import java.io.Closeable; import java.io.IOException; import java.io.InputStream; import java.net.InetAddress; @@ -28,11 +29,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 +70,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; /** @@ -75,7 +79,7 @@ import net.pterodactylus.util.thread.ObjectWrapper; * * @author David ‘Bombe’ Roden <bombe@freenetproject.org> */ -public class FcpClient { +public class FcpClient implements Closeable { /** Object used for synchronization. */ private final Object syncObject = new Object(); @@ -83,9 +87,6 @@ public class FcpClient { /** Listener management. */ private final FcpClientListenerManager fcpClientListenerManager = new FcpClientListenerManager(this); - /** The name of this client. */ - private final String name; - /** The underlying FCP connection. */ private final FcpConnection fcpConnection; @@ -95,37 +96,34 @@ public class FcpClient { /** Whether the client is currently connected. */ private volatile boolean connected; + /** The listener for “connection closed” events. */ + private FcpListener connectionClosedListener; + /** * Creates an FCP client with the given name. * - * @param name - * The name of the FCP client * @throws UnknownHostException * if the hostname “localhost” is unknown */ - public FcpClient(String name) throws UnknownHostException { - this(name, "localhost"); + public FcpClient() throws UnknownHostException { + this("localhost"); } /** * Creates an FCP client. * - * @param name - * The name of the FCP client * @param hostname * The hostname of the Freenet node * @throws UnknownHostException * if the given hostname can not be resolved */ - public FcpClient(String name, String hostname) throws UnknownHostException { - this(name, hostname, FcpConnection.DEFAULT_PORT); + public FcpClient(String hostname) throws UnknownHostException { + this(hostname, FcpConnection.DEFAULT_PORT); } /** * Creates an FCP client. * - * @param name - * The name of the FCP client * @param hostname * The hostname of the Freenet node * @param port @@ -133,36 +131,56 @@ public class FcpClient { * @throws UnknownHostException * if the given hostname can not be resolved */ - public FcpClient(String name, String hostname, int port) throws UnknownHostException { - this(name, InetAddress.getByName(hostname), port); + public FcpClient(String hostname, int port) throws UnknownHostException { + this(InetAddress.getByName(hostname), port); } /** * Creates an FCP client. * - * @param name - * The name of the FCP client * @param host * The host address of the Freenet node */ - public FcpClient(String name, InetAddress host) { - this(name, host, FcpConnection.DEFAULT_PORT); + public FcpClient(InetAddress host) { + this(host, FcpConnection.DEFAULT_PORT); } /** * Creates an FCP client. * - * @param name - * The name of the FCP client * @param host * The host address of the Freenet node * @param port * The Freenet node’s FCP port */ - public FcpClient(String name, InetAddress host, int port) { - this.name = name; - fcpConnection = new FcpConnection(host, port); - fcpConnection.addFcpListener(new FcpAdapter() { + public FcpClient(InetAddress host, int port) { + this(new FcpConnection(host, port), false); + } + + /** + * Creates a new high-level FCP client that will use the given connection. + * This constructor will assume that the FCP connection is already + * connected. + * + * @param fcpConnection + * The FCP connection to use + */ + public FcpClient(FcpConnection fcpConnection) { + this(fcpConnection, true); + } + + /** + * Creates a new high-level FCP client that will use the given connection. + * + * @param fcpConnection + * The FCP connection to use + * @param connected + * The initial status of the FCP connection + */ + public FcpClient(FcpConnection fcpConnection, boolean connected) { + this.fcpConnection = fcpConnection; + this.connected = connected; + connectionClosedListener = new FcpAdapter() { /** * {@inheritDoc} @@ -170,10 +188,11 @@ public class FcpClient { @Override @SuppressWarnings("synthetic-access") public void connectionClosed(FcpConnection fcpConnection, Throwable throwable) { - connected = false; + FcpClient.this.connected = false; fcpClientListenerManager.fireFcpClientDisconnected(); } - }); + }; + fcpConnection.addFcpListener(connectionClosedListener); } // @@ -234,6 +253,15 @@ public class FcpClient { return nodeHello; } + /** + * Returns the underlying FCP connection. + * + * @return The underlying FCP connection + */ + public FcpConnection getConnection() { + return fcpConnection; + } + // // ACTIONS // @@ -241,12 +269,14 @@ public class FcpClient { /** * Connects the FCP client. * + * @param name + * The name of the client * @throws IOException * if an I/O error occurs * @throws FcpException * if an FCP error occurs */ - public void connect() throws IOException, FcpException { + public void connect(final String name) throws IOException, FcpException { checkConnected(false); connected = true; new ExtendedFcpAdapter() { @@ -277,6 +307,94 @@ public class FcpClient { } /** + * Returns the file with the given URI. The retrieved data will be run + * through Freenet’s content filter. + * + * @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 { + return getURI(uri, true); + } + + /** + * Returns the file with the given URI. + * + * @param uri + * The URI to get + * @param filterData + * {@code true} to filter the retrieved data, {@code false} + * otherwise + * @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, final boolean filterData) 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); + clientGet.setFilterData(filterData); + fcpConnection.sendMessage(clientGet); + } + + @Override + public void receivedGetFailed(FcpConnection fcpConnection, GetFailed getFailed) { + if (!getFailed.getIdentifier().equals(identifier)) { + return; + } + if ((getFailed.getCode() == 27) || (getFailed.getCode() == 24)) { + /* redirect! */ + String newUri = getFailed.getRedirectURI(); + getResult.realUri(newUri); + try { + ClientGet clientGet = new ClientGet(newUri, identifier); + clientGet.setFilterData(filterData); + fcpConnection.sendMessage(clientGet); + } 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() { @@ -287,6 +405,14 @@ public class FcpClient { } /** + * {@inheritDoc} + */ + @Override + public void close() { + disconnect(); + } + + /** * Returns whether this client is currently connected. * * @return {@code true} if the client is currently connected, {@code false} @@ -296,6 +422,13 @@ public class FcpClient { return connected; } + /** + * Detaches this client from its underlying FCP connection. + */ + public void detach() { + fcpConnection.removeFcpListener(connectionClosedListener); + } + // // PEER MANAGEMENT // @@ -742,6 +875,7 @@ public class FcpClient { /** * {@inheritDoc} */ + @Override public boolean filterObject(Request request) { return request instanceof GetRequest; } @@ -767,6 +901,7 @@ public class FcpClient { /** * {@inheritDoc} */ + @Override public boolean filterObject(Request request) { return request instanceof PutRequest; }