Add “connected” flag.
[jFCPlib.git] / src / net / pterodactylus / fcp / highlevel / FcpClient.java
index 4af4426..7f2d8bd 100644 (file)
@@ -60,6 +60,8 @@ import net.pterodactylus.fcp.RemovePeer;
 import net.pterodactylus.fcp.SSKKeypair;
 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.thread.ObjectWrapper;
 
 /**
@@ -79,6 +81,9 @@ public class FcpClient {
        /** The underlying FCP connection. */
        private final FcpConnection fcpConnection;
 
+       /** Whether the client is currently connected. */
+       private volatile boolean connected;
+
        /**
         * Creates an FCP client with the given name.
         *
@@ -161,6 +166,8 @@ public class FcpClient {
         *             if an FCP error occurs
         */
        public void connect() throws IOException, FcpException {
+               checkConnected(false);
+               connected = true;
                new ExtendedFcpAdapter() {
 
                        /**
@@ -254,6 +261,78 @@ public class FcpClient {
        }
 
        /**
+        * Returns all darknet peers.
+        *
+        * @param withMetadata
+        *            <code>true</code> to include peer metadata
+        * @param withVolatile
+        *            <code>true</code> to include volatile peer data
+        * @return A set containing the node’s darknet peers
+        * @throws IOException
+        *             if an I/O error occurs
+        * @throws FcpException
+        *             if an FCP error occurs
+        */
+       public Collection<Peer> getDarknetPeers(boolean withMetadata, boolean withVolatile) throws IOException, FcpException {
+               Collection<Peer> allPeers = getPeers(withMetadata, withVolatile);
+               Collection<Peer> darknetPeers = new HashSet<Peer>();
+               for (Peer peer : allPeers) {
+                       if (!peer.isOpennet() && !peer.isSeed()) {
+                               darknetPeers.add(peer);
+                       }
+               }
+               return darknetPeers;
+       }
+
+       /**
+        * Returns all opennet peers.
+        *
+        * @param withMetadata
+        *            <code>true</code> to include peer metadata
+        * @param withVolatile
+        *            <code>true</code> to include volatile peer data
+        * @return A set containing the node’s opennet peers
+        * @throws IOException
+        *             if an I/O error occurs
+        * @throws FcpException
+        *             if an FCP error occurs
+        */
+       public Collection<Peer> getOpennetPeers(boolean withMetadata, boolean withVolatile) throws IOException, FcpException {
+               Collection<Peer> allPeers = getPeers(withMetadata, withVolatile);
+               Collection<Peer> opennetPeers = new HashSet<Peer>();
+               for (Peer peer : allPeers) {
+                       if (peer.isOpennet() && !peer.isSeed()) {
+                               opennetPeers.add(peer);
+                       }
+               }
+               return opennetPeers;
+       }
+
+       /**
+        * Returns all seed peers.
+        *
+        * @param withMetadata
+        *            <code>true</code> to include peer metadata
+        * @param withVolatile
+        *            <code>true</code> to include volatile peer data
+        * @return A set containing the node’s seed peers
+        * @throws IOException
+        *             if an I/O error occurs
+        * @throws FcpException
+        *             if an FCP error occurs
+        */
+       public Collection<Peer> getSeedPeers(boolean withMetadata, boolean withVolatile) throws IOException, FcpException {
+               Collection<Peer> allPeers = getPeers(withMetadata, withVolatile);
+               Collection<Peer> seedPeers = new HashSet<Peer>();
+               for (Peer peer : allPeers) {
+                       if (peer.isSeed()) {
+                               seedPeers.add(peer);
+                       }
+               }
+               return seedPeers;
+       }
+
+       /**
         * Adds the given peer to the node.
         *
         * @param peer
@@ -565,9 +644,55 @@ public class FcpClient {
         *             if an FCP error occurs
         */
        public Collection<Request> getGetRequests(final boolean global) throws IOException, FcpException {
-               return getRequests(global);
+               return Filters.filteredCollection(getRequests(global), new Filter<Request>() {
+
+                       /**
+                        * {@inheritDoc}
+                        */
+                       public boolean filterObject(Request request) {
+                               return request instanceof GetRequest;
+                       }
+               });
        }
 
+       /**
+        * Returns all currently visible persistent put requests.
+        *
+        * @param global
+        *            <code>true</code> to return put requests from the global
+        *            queue, <code>false</code> to only show requests from the
+        *            client-local queue
+        * @return All put requests
+        * @throws IOException
+        *             if an I/O error occurs
+        * @throws FcpException
+        *             if an FCP error occurs
+        */
+       public Collection<Request> getPutRequests(final boolean global) throws IOException, FcpException {
+               return Filters.filteredCollection(getRequests(global), new Filter<Request>() {
+
+                       /**
+                        * {@inheritDoc}
+                        */
+                       public boolean filterObject(Request request) {
+                               return request instanceof PutRequest;
+                       }
+               });
+       }
+
+       /**
+        * Returns all currently visible persistent requests.
+        *
+        * @param global
+        *            <code>true</code> to return requests from the global queue,
+        *            <code>false</code> to only show requests from the client-local
+        *            queue
+        * @return All requests
+        * @throws IOException
+        *             if an I/O error occurs
+        * @throws FcpException
+        *             if an FCP error occurs
+        */
        public Collection<Request> getRequests(final boolean global) throws IOException, FcpException {
                final Map<String, Request> requests = Collections.synchronizedMap(new HashMap<String, Request>());
                new ExtendedFcpAdapter() {
@@ -688,6 +813,28 @@ public class FcpClient {
        }
 
        /**
+        * Checks whether the connection is in the required state.
+        *
+        * @param connected
+        *            The required connection state
+        * @throws FcpException
+        *             if the connection is not in the required state
+        */
+       private void checkConnected(boolean connected) throws FcpException {
+               if (this.connected != connected) {
+                       throw new FcpException("Client is " + (connected ? "not" : "already") + " connected.");
+               }
+       }
+
+       /**
+        * Tells the client that it is now disconnected. This method is called by
+        * {@link ExtendedFcpAdapter} only.
+        */
+       private void setDisconnected() {
+               connected = false;
+       }
+
+       /**
         * Implementation of an {@link FcpListener} that can store an
         * {@link FcpException} and wait for the arrival of a certain command.
         *
@@ -719,6 +866,7 @@ public class FcpClient {
                 */
                @SuppressWarnings("synthetic-access")
                public void execute() throws IOException, FcpException {
+                       checkConnected(true);
                        fcpConnection.addFcpListener(this);
                        try {
                                run();
@@ -730,10 +878,14 @@ public class FcpClient {
                                                /* ignore, we’ll loop. */
                                        }
                                }
+                       } catch (IOException ioe1) {
+                               setDisconnected();
+                               throw ioe1;
                        } finally {
                                fcpConnection.removeFcpListener(this);
                        }
                        if (fcpException != null) {
+                               setDisconnected();
                                throw fcpException;
                        }
                }