Merge branch 'release-0.1.4' v0.1.4
authorDavid ‘Bombe’ Roden <bombe@freenetproject.org>
Fri, 10 Jun 2016 16:45:51 +0000 (18:45 +0200)
committerDavid ‘Bombe’ Roden <bombe@freenetproject.org>
Fri, 10 Jun 2016 16:45:51 +0000 (18:45 +0200)
69 files changed:
pom.xml
src/main/java/net/pterodactylus/fcp/AddPeer.java
src/main/java/net/pterodactylus/fcp/AllData.java
src/main/java/net/pterodactylus/fcp/BaseMessage.java
src/main/java/net/pterodactylus/fcp/ClientGet.java
src/main/java/net/pterodactylus/fcp/CloseConnectionDuplicateClientName.java
src/main/java/net/pterodactylus/fcp/ConfigData.java
src/main/java/net/pterodactylus/fcp/DataFound.java
src/main/java/net/pterodactylus/fcp/EndListPeerNotes.java
src/main/java/net/pterodactylus/fcp/EndListPeers.java
src/main/java/net/pterodactylus/fcp/EndListPersistentRequests.java
src/main/java/net/pterodactylus/fcp/FCPPluginMessage.java
src/main/java/net/pterodactylus/fcp/FCPPluginReply.java
src/main/java/net/pterodactylus/fcp/FcpAdapter.java
src/main/java/net/pterodactylus/fcp/FcpConnection.java
src/main/java/net/pterodactylus/fcp/FcpConnectionHandler.java
src/main/java/net/pterodactylus/fcp/FcpListener.java
src/main/java/net/pterodactylus/fcp/FcpListenerManager.java
src/main/java/net/pterodactylus/fcp/FcpMessage.java
src/main/java/net/pterodactylus/fcp/FcpUtils.java
src/main/java/net/pterodactylus/fcp/FinishedCompression.java
src/main/java/net/pterodactylus/fcp/FreenetBase64.java [new file with mode: 0644]
src/main/java/net/pterodactylus/fcp/GetConfig.java
src/main/java/net/pterodactylus/fcp/GetFailed.java
src/main/java/net/pterodactylus/fcp/GetNode.java
src/main/java/net/pterodactylus/fcp/GetPluginInfo.java
src/main/java/net/pterodactylus/fcp/IdentifierCollision.java
src/main/java/net/pterodactylus/fcp/Key.java [new file with mode: 0644]
src/main/java/net/pterodactylus/fcp/ListPeer.java
src/main/java/net/pterodactylus/fcp/ListPeerNotes.java
src/main/java/net/pterodactylus/fcp/LoadPlugin.java [new file with mode: 0644]
src/main/java/net/pterodactylus/fcp/ModifyConfig.java
src/main/java/net/pterodactylus/fcp/ModifyPeer.java
src/main/java/net/pterodactylus/fcp/ModifyPeerNote.java
src/main/java/net/pterodactylus/fcp/NodeData.java
src/main/java/net/pterodactylus/fcp/NodeHello.java
src/main/java/net/pterodactylus/fcp/Peer.java
src/main/java/net/pterodactylus/fcp/PeerNote.java
src/main/java/net/pterodactylus/fcp/PeerNoteType.java [new file with mode: 0644]
src/main/java/net/pterodactylus/fcp/PeerRemoved.java
src/main/java/net/pterodactylus/fcp/PersistentGet.java
src/main/java/net/pterodactylus/fcp/PersistentPut.java
src/main/java/net/pterodactylus/fcp/PersistentPutDir.java
src/main/java/net/pterodactylus/fcp/PersistentRequestModified.java
src/main/java/net/pterodactylus/fcp/PersistentRequestRemoved.java
src/main/java/net/pterodactylus/fcp/PluginInfo.java
src/main/java/net/pterodactylus/fcp/PluginRemoved.java [new file with mode: 0644]
src/main/java/net/pterodactylus/fcp/ProtocolError.java
src/main/java/net/pterodactylus/fcp/PutFailed.java
src/main/java/net/pterodactylus/fcp/PutFetchable.java
src/main/java/net/pterodactylus/fcp/PutSuccessful.java
src/main/java/net/pterodactylus/fcp/ReloadPlugin.java [new file with mode: 0644]
src/main/java/net/pterodactylus/fcp/RemovePeer.java
src/main/java/net/pterodactylus/fcp/RemovePlugin.java [new file with mode: 0644]
src/main/java/net/pterodactylus/fcp/RequestProgress.java [new file with mode: 0644]
src/main/java/net/pterodactylus/fcp/SSKKeypair.java
src/main/java/net/pterodactylus/fcp/SimpleProgress.java
src/main/java/net/pterodactylus/fcp/StartedCompression.java
src/main/java/net/pterodactylus/fcp/SubscribeUSK.java
src/main/java/net/pterodactylus/fcp/SubscribedUSK.java [new file with mode: 0644]
src/main/java/net/pterodactylus/fcp/SubscribedUSKUpdate.java
src/main/java/net/pterodactylus/fcp/TestDDAComplete.java
src/main/java/net/pterodactylus/fcp/TestDDAReply.java
src/main/java/net/pterodactylus/fcp/TestDDAResponse.java
src/main/java/net/pterodactylus/fcp/URIGenerated.java
src/main/java/net/pterodactylus/fcp/UnknownNodeIdentifier.java
src/main/java/net/pterodactylus/fcp/UnsubscribeUSK.java [new file with mode: 0644]
src/test/java/net/pterodactylus/fcp/ModifyPeerNoteTest.java [new file with mode: 0644]
src/test/java/net/pterodactylus/fcp/PeerNoteTest.java [new file with mode: 0644]

diff --git a/pom.xml b/pom.xml
index 4309367..26dbf4c 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -2,14 +2,14 @@
        <modelVersion>4.0.0</modelVersion>
        <groupId>net.pterodactylus</groupId>
        <artifactId>jFCPlib</artifactId>
-       <version>0.1.3</version>
+       <version>0.1.4</version>
        <name>jFCPlib</name>
        <packaging>jar</packaging>
        <distributionManagement>
                <repository>
                        <id>pterodactylus</id>
                        <name>pterodactylus.net Maven Repository</name>
-                       <url>scp://maven@maven.pterodactylus.net/home/maven/repository</url>
+                       <url>scpexe://maven@maven.pterodactylus.net/home/maven/repository</url>
                </repository>
        </distributionManagement>
        <dependencies>
                <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        </properties>
        <build>
+               <extensions>
+                       <extension>
+                               <groupId>org.apache.maven.wagon</groupId>
+                               <artifactId>wagon-ssh-external</artifactId>
+                               <version>2.9</version>
+                       </extension>
+               </extensions>
                <plugins>
                        <plugin>
                                <groupId>org.apache.maven.plugins</groupId>
index e9ad80d..696a017 100644 (file)
@@ -46,6 +46,11 @@ public class AddPeer extends FcpMessage {
                setField("File", file);
        }
 
+       public AddPeer(String identifier, String file) {
+               this(file);
+               setField("Identifier", identifier);
+       }
+
        /**
         * Creates a new “AddPeer” request that reads the noderef of the peer from
         * the given URL.
@@ -58,6 +63,11 @@ public class AddPeer extends FcpMessage {
                setField("URL", String.valueOf(url));
        }
 
+       public AddPeer(String identifier, URL url) {
+               this(url);
+               setField("Identifier", identifier);
+       }
+
        /**
         * Creates a new “AddPeer” request that adds the peer given by the noderef.
         *
@@ -69,6 +79,11 @@ public class AddPeer extends FcpMessage {
                setNodeRef(nodeRef);
        }
 
+       public AddPeer(String identifier, NodeRef nodeRef) {
+               this(nodeRef);
+               setField("Identifier", identifier);
+       }
+
        //
        // PRIVATE METHODS
        //
@@ -80,7 +95,7 @@ public class AddPeer extends FcpMessage {
         *            The noderef of the peer
         */
        private void setNodeRef(NodeRef nodeRef) {
-               setField("lastGoodVersion", nodeRef.getLastGoodVersion().toString());
+               setField("lastGoodVersion", String.valueOf(nodeRef.getLastGoodVersion()));
                setField("opennet", String.valueOf(nodeRef.isOpennet()));
                setField("identity", nodeRef.getIdentity());
                setField("myName", nodeRef.getMyName());
index b4daa27..621e993 100644 (file)
@@ -44,7 +44,7 @@ public class AllData extends BaseMessage implements Identifiable {
         * @param payloadInputStream
         *            The payload
         */
-       AllData(FcpMessage receivedMessage, InputStream payloadInputStream) {
+       public AllData(FcpMessage receivedMessage, InputStream payloadInputStream) {
                super(receivedMessage);
                this.payloadInputStream = payloadInputStream;
        }
index a5ea020..cca7d67 100644 (file)
@@ -57,7 +57,7 @@ public class BaseMessage {
         * @return The content of the field, or <code>null</code> if there is no
         *         such field
         */
-       protected String getField(String field) {
+       public String getField(String field) {
                return receivedMessage.getField(field);
        }
 
@@ -67,7 +67,7 @@ public class BaseMessage {
         * @see FcpMessage#getFields()
         * @return All fields from the message
         */
-       protected Map<String, String> getFields() {
+       public Map<String, String> getFields() {
                return receivedMessage.getFields();
        }
 
index 1126824..d340cf0 100644 (file)
@@ -131,6 +131,10 @@ public class ClientGet extends FcpMessage {
                setField("PriorityClass", String.valueOf(priority));
        }
 
+       public void setRealTimeFlag(boolean realTimeFlag) {
+               setField("RealTimeFlag", String.valueOf(realTimeFlag));
+       }
+
        /**
         * Sets the persistence of the request.
         *
index db0ff0d..14775ae 100644 (file)
@@ -32,7 +32,7 @@ public class CloseConnectionDuplicateClientName extends BaseMessage {
         * @param receivedMessage
         *            The received message
         */
-       CloseConnectionDuplicateClientName(FcpMessage receivedMessage) {
+       public CloseConnectionDuplicateClientName(FcpMessage receivedMessage) {
                super(receivedMessage);
        }
 
index 4eb7954..c05eb9f 100644 (file)
@@ -32,7 +32,7 @@ public class ConfigData extends BaseMessage {
         * @param receivedMessage
         *            The received message
         */
-       ConfigData(FcpMessage receivedMessage) {
+       public ConfigData(FcpMessage receivedMessage) {
                super(receivedMessage);
        }
 
index 742f6ac..c00709a 100644 (file)
@@ -33,7 +33,7 @@ public class DataFound extends BaseMessage implements Identifiable {
         * @param receivedMessage
         *            The received message
         */
-       DataFound(FcpMessage receivedMessage) {
+       public DataFound(FcpMessage receivedMessage) {
                super(receivedMessage);
        }
 
index 31a52af..88e8525 100644 (file)
@@ -33,7 +33,7 @@ public class EndListPeerNotes extends BaseMessage {
         * @param fcpMessage
         *            The received message
         */
-       EndListPeerNotes(FcpMessage fcpMessage) {
+       public EndListPeerNotes(FcpMessage fcpMessage) {
                super(fcpMessage);
        }
 
index bb98f23..5a505d0 100644 (file)
@@ -31,7 +31,7 @@ public class EndListPeers extends BaseMessage implements Identifiable {
         * @param receivedMessage
         *            The message that was received
         */
-       EndListPeers(FcpMessage receivedMessage) {
+       public EndListPeers(FcpMessage receivedMessage) {
                super(receivedMessage);
        }
 
index baa8de2..702cc95 100644 (file)
@@ -33,7 +33,7 @@ public class EndListPersistentRequests extends BaseMessage {
         * @param receivedMessage
         *            The received message
         */
-       EndListPersistentRequests(FcpMessage receivedMessage) {
+       public EndListPersistentRequests(FcpMessage receivedMessage) {
                super(receivedMessage);
        }
 
index 99cb0d0..92a9949 100644 (file)
@@ -18,6 +18,8 @@
 
 package net.pterodactylus.fcp;
 
+import java.io.InputStream;
+
 /**
  * An “CPPluginMessage” sends a message with custom parameters and (optional)
  * payload to a plugin.
@@ -27,24 +29,23 @@ package net.pterodactylus.fcp;
 public class FCPPluginMessage extends FcpMessage {
 
        /**
-        * Creates a new “FCPPluginMessage” message for the given plugin.
-        *
-        * @param pluginClass
-        *            The name of the plugin class
+        * @deprecated Use {@link #FCPPluginMessage(String, String)} instead
         */
+       @Deprecated
        public FCPPluginMessage(String pluginClass) {
                super("FCPPluginMessage");
                setField("PluginName", pluginClass);
        }
 
+       public FCPPluginMessage(String identifier, String pluginClass) {
+               this(pluginClass);
+               setField("Identifier", identifier);
+       }
+
        /**
-        * Sets the identifier of the request. Though this is still optional you
-        * are encouraged to include it because the plugin might reply in random
-        * order to requests.
-        *
-        * @param identifier
-        *            The identifier of the request
+        * @deprecated Use {@link #FCPPluginMessage(String, String)} instead
         */
+       @Deprecated
        public void setIdentifier(String identifier) {
                setField("Identifier", identifier);
        }
@@ -53,24 +54,25 @@ public class FCPPluginMessage extends FcpMessage {
         * Sets a custom parameter for the plugin.
         *
         * @param key
-        *            The key of the parameter
+        *      The key of the parameter
         * @param value
-        *            The value of the parameter
+        *      The value of the parameter
         */
        public void setParameter(String key, String value) {
                setField("Param." + key, value);
        }
 
        /**
-        * Sets the length of data of the optional payload. If you call this method
-        * you also have to call
-        * {@link #setPayloadInputStream(java.io.InputStream)} !
-        *
-        * @param dataLength
-        *            The length of data in the payload input stream
+        * @deprecated Use {@link #setData(InputStream, long)} instead
         */
+       @Deprecated
        public void setDataLength(long dataLength) {
                setField("DataLength", String.valueOf(dataLength));
        }
 
+       public void setData(InputStream payloadInputStream, long dataLength) {
+               setPayloadInputStream(payloadInputStream);
+               setDataLength(dataLength);
+       }
+
 }
index 44e96ba..0ed55f0 100644 (file)
@@ -42,7 +42,7 @@ public class FCPPluginReply extends BaseMessage implements Identifiable {
         * @param payloadInputStream
         *            The optional input stream for the payload
         */
-       FCPPluginReply(FcpMessage receivedMessage, InputStream payloadInputStream) {
+       public FCPPluginReply(FcpMessage receivedMessage, InputStream payloadInputStream) {
                super(receivedMessage);
                this.payloadInputStream = payloadInputStream;
        }
index 063d363..0d0debc 100644 (file)
@@ -253,6 +253,11 @@ public class FcpAdapter implements FcpListener {
                /* empty. */
        }
 
+       @Override
+       public void receivedSubscribedUSK(FcpConnection fcpConnection, SubscribedUSK subscribedUSK) {
+               /* empty. */
+       }
+
        /**
         * {@inheritDoc}
         */
@@ -273,6 +278,11 @@ public class FcpAdapter implements FcpListener {
         * {@inheritDoc}
         */
        @Override
+       public void receivedPluginRemoved(FcpConnection fcpConnection, PluginRemoved pluginRemoved) {
+               /* empty. */
+       }
+
+       @Override
        public void receivedFCPPluginReply(FcpConnection fcpConnection, FCPPluginReply fcpPluginReply) {
                /* empty. */
        }
index 66377a2..b7b99bf 100644 (file)
@@ -31,6 +31,8 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.logging.Logger;
 
+import net.pterodactylus.fcp.FcpUtils.TempInputStream;
+
 /**
  * An FCP connection to a Freenet node.
  *
@@ -156,6 +158,10 @@ public class FcpConnection implements Closeable {
                fcpListenerManager.removeListener(fcpListener);
        }
 
+       public synchronized boolean isClosed() {
+               return connectionHandler == null;
+       }
+
        //
        // ACTIONS
        //
@@ -223,7 +229,7 @@ public class FcpConnection implements Closeable {
         * @param fcpMessage
         *            The received message
         */
-       void handleMessage(FcpMessage fcpMessage) {
+       void handleMessage(FcpMessage fcpMessage) throws IOException{
                logger.fine("received message: " + fcpMessage.getName());
                String messageName = fcpMessage.getName();
                countMessage(messageName);
@@ -261,16 +267,13 @@ public class FcpConnection implements Closeable {
                        fcpListenerManager.fireReceivedDataFound(new DataFound(fcpMessage));
                } else if ("SubscribedUSKUpdate".equals(messageName)) {
                        fcpListenerManager.fireReceivedSubscribedUSKUpdate(new SubscribedUSKUpdate(fcpMessage));
+               } else if ("SubscribedUSK".equals(messageName)) {
+                       fcpListenerManager.fireReceivedSubscribedUSK(new SubscribedUSK(fcpMessage));
                } else if ("IdentifierCollision".equals(messageName)) {
                        fcpListenerManager.fireReceivedIdentifierCollision(new IdentifierCollision(fcpMessage));
                } else if ("AllData".equals(messageName)) {
-                       LimitedInputStream payloadInputStream = getInputStream(FcpUtils.safeParseLong(fcpMessage.getField("DataLength")));
+                       InputStream payloadInputStream = getInputStream(FcpUtils.safeParseLong(fcpMessage.getField("DataLength")));
                        fcpListenerManager.fireReceivedAllData(new AllData(fcpMessage, payloadInputStream));
-                       try {
-                               payloadInputStream.consume();
-                       } catch (IOException ioe1) {
-                               /* well, ignore. when the connection handler fails, all fails. */
-                       }
                } else if ("EndListPeerNotes".equals(messageName)) {
                        fcpListenerManager.fireReceivedEndListPeerNotes(new EndListPeerNotes(fcpMessage));
                } else if ("EndListPeers".equals(messageName)) {
@@ -288,15 +291,12 @@ public class FcpConnection implements Closeable {
                } else if ("UnknownNodeIdentifier".equals(messageName)) {
                        fcpListenerManager.fireReceivedUnknownNodeIdentifier(new UnknownNodeIdentifier(fcpMessage));
                } else if ("FCPPluginReply".equals(messageName)) {
-                       LimitedInputStream payloadInputStream = getInputStream(FcpUtils.safeParseLong(fcpMessage.getField("DataLength")));
+                       InputStream payloadInputStream = getInputStream(FcpUtils.safeParseLong(fcpMessage.getField("DataLength")));
                        fcpListenerManager.fireReceivedFCPPluginReply(new FCPPluginReply(fcpMessage, payloadInputStream));
-                       try {
-                               payloadInputStream.consume();
-                       } catch (IOException ioe1) {
-                               /* ignore. */
-                       }
                } else if ("PluginInfo".equals(messageName)) {
                        fcpListenerManager.fireReceivedPluginInfo(new PluginInfo(fcpMessage));
+               } else if ("PluginRemoved".equals(messageName)) {
+                       fcpListenerManager.fireReceivedPluginRemoved(new PluginRemoved(fcpMessage));
                } else if ("NodeData".equals(messageName)) {
                        fcpListenerManager.fireReceivedNodeData(new NodeData(fcpMessage));
                } else if ("TestDDAReply".equals(messageName)) {
@@ -356,142 +356,8 @@ public class FcpConnection implements Closeable {
                logger.finest("count for " + name + ": " + (oldValue + 1));
        }
 
-       /**
-        * Returns a limited input stream from the node’s input stream.
-        *
-        * @param dataLength
-        *            The length of the stream
-        * @return The limited input stream
-        */
-       private synchronized LimitedInputStream getInputStream(long dataLength) {
-               if (dataLength <= 0) {
-                       return new LimitedInputStream(null, 0);
-               }
-               return new LimitedInputStream(remoteInputStream, dataLength);
-       }
-
-       /**
-        * A wrapper around an {@link InputStream} that only supplies a limit
-        * number of bytes from the underlying input stream.
-        *
-        * @author David ‘Bombe’ Roden &lt;bombe@freenetproject.org&gt;
-        */
-       private static class LimitedInputStream extends FilterInputStream {
-
-               /** The remaining number of bytes that can be read. */
-               private long remaining;
-
-               /**
-                * Creates a new LimitedInputStream that supplies at most
-                * <code>length</code> bytes from the given input stream.
-                *
-                * @param inputStream
-                *            The input stream
-                * @param length
-                *            The number of bytes to read
-                */
-               public LimitedInputStream(InputStream inputStream, long length) {
-                       super(inputStream);
-                       remaining = length;
-               }
-
-               /**
-                * @see java.io.FilterInputStream#available()
-                */
-               @Override
-               public synchronized int available() throws IOException {
-                       if (remaining == 0) {
-                               return 0;
-                       }
-                       return (int) Math.min(super.available(), Math.min(Integer.MAX_VALUE, remaining));
-               }
-
-               /**
-                * @see java.io.FilterInputStream#read()
-                */
-               @Override
-               public synchronized int read() throws IOException {
-                       int read = -1;
-                       if (remaining > 0) {
-                               read = super.read();
-                               remaining--;
-                       }
-                       return read;
-               }
-
-               /**
-                * @see java.io.FilterInputStream#read(byte[], int, int)
-                */
-               @Override
-               public synchronized int read(byte[] b, int off, int len) throws IOException {
-                       if (remaining == 0) {
-                               return -1;
-                       }
-                       int toCopy = (int) Math.min(len, Math.min(remaining, Integer.MAX_VALUE));
-                       int read = super.read(b, off, toCopy);
-                       remaining -= read;
-                       return read;
-               }
-
-               /**
-                * @see java.io.FilterInputStream#skip(long)
-                */
-               @Override
-               public synchronized long skip(long n) throws IOException {
-                       if ((n < 0) || (remaining == 0)) {
-                               return 0;
-                       }
-                       long skipped = super.skip(Math.min(n, remaining));
-                       remaining -= skipped;
-                       return skipped;
-               }
-
-               /**
-                * {@inheritDoc} This method does nothing, as {@link #mark(int)} and
-                * {@link #reset()} are not supported.
-                *
-                * @see java.io.FilterInputStream#mark(int)
-                */
-               @Override
-               public synchronized void mark(int readlimit) {
-                       /* do nothing. */
-               }
-
-               /**
-                * {@inheritDoc}
-                *
-                * @see java.io.FilterInputStream#markSupported()
-                * @return <code>false</code>
-                */
-               @Override
-               public boolean markSupported() {
-                       return false;
-               }
-
-               /**
-                * {@inheritDoc} This method does nothing, as {@link #mark(int)} and
-                * {@link #reset()} are not supported.
-                *
-                * @see java.io.FilterInputStream#reset()
-                */
-               @Override
-               public synchronized void reset() throws IOException {
-                       /* do nothing. */
-               }
-
-               /**
-                * Consumes the input stream, i.e. read all bytes until the limit is
-                * reached.
-                *
-                * @throws IOException
-                *             if an I/O error occurs
-                */
-               public synchronized void consume() throws IOException {
-                       while (remaining > 0) {
-                               skip(remaining);
-                       }
-               }
-
+       private synchronized InputStream getInputStream(long dataLength) throws IOException {
+               return new TempInputStream(remoteInputStream, dataLength);
        }
 
 }
index 36be123..256efef 100644 (file)
@@ -18,6 +18,7 @@
 
 package net.pterodactylus.fcp;
 
+import java.io.EOFException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.ByteBuffer;
@@ -76,8 +77,9 @@ class FcpConnectionHandler implements Runnable {
                        }
                        try {
                                String line = readLine();
-                               logger.log(Level.FINEST, "read line: %1$s", line);
+                               logger.log(Level.FINEST, String.format("read line: %1$s", line));
                                if (line == null) {
+                                       throwable = new EOFException();
                                        break;
                                }
                                if (line.length() == 0) {
index 02eeed5..b96885f 100644 (file)
@@ -309,6 +309,8 @@ public interface FcpListener extends EventListener {
         */
        public void receivedPersistentRequestRemoved(FcpConnection fcpConnection, PersistentRequestRemoved persistentRequestRemoved);
 
+       void receivedSubscribedUSK(FcpConnection fcpConnection, SubscribedUSK subscribedUSK);
+
        /**
         * Notifies a listener that a “SubscribedUSKUpdate” message was received.
         *
@@ -329,6 +331,8 @@ public interface FcpListener extends EventListener {
         */
        public void receivedPluginInfo(FcpConnection fcpConnection, PluginInfo pluginInfo);
 
+       void receivedPluginRemoved(FcpConnection fcpConnection, PluginRemoved pluginRemoved);
+
        /**
         * Notifies a listener that an “FCPPluginReply“ message was received.
         *
index 7969da1..a25f3bf 100644 (file)
@@ -438,6 +438,12 @@ public class FcpListenerManager {
                }
        }
 
+       public void fireReceivedSubscribedUSK(SubscribedUSK subscribedUSK) {
+               for (FcpListener fcpListener : getListeners()) {
+                       fcpListener.receivedSubscribedUSK(getSource(), subscribedUSK);
+               }
+       }
+
        /**
         * Notifies all listeners that a “SubscribedUSKUpdate” message was
         * received.
@@ -466,6 +472,12 @@ public class FcpListenerManager {
                }
        }
 
+       public void fireReceivedPluginRemoved(PluginRemoved pluginRemoved) {
+               for (FcpListener fcpListener : getListeners()) {
+                       fcpListener.receivedPluginRemoved(getSource(), pluginRemoved);
+               }
+       }
+
        /**
         * Notifies all listeners that an “FCPPluginReply” message was received.
         *
index ed4ae46..d9fff9b 100644 (file)
@@ -110,6 +110,11 @@ public class FcpMessage implements Iterable<String> {
                fields.put(field, value);
        }
 
+       public FcpMessage put(String field, String value) {
+               setField(field, value);
+               return this;
+       }
+
        /**
         * Returns the value of the given field.
         *
index 415cf1a..26a407c 100644 (file)
@@ -268,7 +268,9 @@ public class FcpUtils {
                                throw new EOFException("stream reached eof");
                        }
                        destination.write(buffer, 0, read);
-                       remaining -= read;
+                       if (remaining > 0) {
+                               remaining -= read;
+                       }
                }
        }
 
index 91c0341..d6c3ac7 100644 (file)
@@ -33,7 +33,7 @@ public class FinishedCompression extends BaseMessage implements Identifiable {
         * @param receivedMessage
         *            The message that was recevied
         */
-       FinishedCompression(FcpMessage receivedMessage) {
+       public FinishedCompression(FcpMessage receivedMessage) {
                super(receivedMessage);
        }
 
diff --git a/src/main/java/net/pterodactylus/fcp/FreenetBase64.java b/src/main/java/net/pterodactylus/fcp/FreenetBase64.java
new file mode 100644 (file)
index 0000000..4c3422d
--- /dev/null
@@ -0,0 +1,90 @@
+package net.pterodactylus.fcp;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+/**
+ * Freenet-specific Base64 implementation.
+ *
+ * @author <a href="mailto:bombe@freenetproject.org">David ‘Bombe’ Roden</a>
+ */
+public class FreenetBase64 {
+
+       private static final char[] FREENET_BASE64_ALPHABET =
+               "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~-".toCharArray();
+       private static final int[] REVERSE_FREENET_BASE64_ALPHABET = reverse(FREENET_BASE64_ALPHABET);
+
+       private static int[] reverse(char[] alphabet) {
+               String alphabetString = new String(alphabet);
+               int[] reversedAlphabet = new int[128];
+               for (int i = 0; i < 128; i++) {
+                       if (alphabetString.indexOf(i) > -1) {
+                               reversedAlphabet[i] = alphabetString.indexOf(i);
+                       } else {
+                               reversedAlphabet[i] = -1;
+                       }
+               }
+               return reversedAlphabet;
+       }
+
+       public String encode(byte[] data) {
+               StringBuilder result = new StringBuilder();
+               int currentValue = 0;
+               int index = 0;
+               while (index < data.length) {
+                       currentValue = (currentValue << 8) | data[index];
+                       if (index % 3 == 2) {
+                               result.append(FREENET_BASE64_ALPHABET[(currentValue >> 18) & 0x3f]);
+                               result.append(FREENET_BASE64_ALPHABET[(currentValue >> 12) & 0x3f]);
+                               result.append(FREENET_BASE64_ALPHABET[(currentValue >> 6) & 0x3f]);
+                               result.append(FREENET_BASE64_ALPHABET[currentValue & 0x3f]);
+                       }
+                       index++;
+               }
+               if (index % 3 == 1) {
+                       result.append(FREENET_BASE64_ALPHABET[(currentValue >> 2) & 0x3f]);
+                       result.append(FREENET_BASE64_ALPHABET[(currentValue << 4) & 0x3f]);
+                       result.append("==");
+               } else if (index % 3 == 2) {
+                       result.append(FREENET_BASE64_ALPHABET[(currentValue >> 10) & 0x3f]);
+                       result.append(FREENET_BASE64_ALPHABET[(currentValue >> 4) & 0x3f]);
+                       result.append(FREENET_BASE64_ALPHABET[(currentValue << 2) & 0x3f]);
+                       result.append("=");
+               }
+               return result.toString();
+       }
+
+       public byte[] decode(String data) {
+               ByteArrayOutputStream dataOutput = new ByteArrayOutputStream(data.length() * 3 / 4);
+               try {
+                       int currentValue = 0;
+                       int index = 0;
+                       for (char c : data.toCharArray()) {
+                               if (c == '=') {
+                                       break;
+                               }
+                               currentValue = (currentValue << 6) | REVERSE_FREENET_BASE64_ALPHABET[c];
+                               if (index % 4 == 3) {
+                                       dataOutput.write((currentValue >> 16) & 0xff);
+                                       dataOutput.write((currentValue >> 8) & 0xff);
+                                       dataOutput.write(currentValue & 0xff);
+                               }
+                               index++;
+                       }
+                       if (index % 4 == 2) {
+                               dataOutput.write((currentValue >> 4) & 0xff);
+                       } else if (index % 4 == 3) {
+                               dataOutput.write((currentValue >> 10) & 0xff);
+                               dataOutput.write((currentValue >> 2) & 0xff);
+                       }
+                       return dataOutput.toByteArray();
+               } finally {
+                       try {
+                               dataOutput.close();
+                       } catch (IOException e) {
+                               throw new RuntimeException(e);
+                       }
+               }
+       }
+
+}
index 230a790..3e381bf 100644 (file)
@@ -33,6 +33,11 @@ public class GetConfig extends FcpMessage {
                super("GetConfig");
        }
 
+       public GetConfig(String identifer) {
+               this();
+               setField("Identifier", identifer);
+       }
+
        /**
         * Sets whether the {@link ConfigData} result message shall include the
         * current values.
index 01ec1c8..10c22b5 100644 (file)
@@ -38,7 +38,7 @@ public class GetFailed extends BaseMessage implements Identifiable {
         * @param receivedMessage
         *            The received message
         */
-       GetFailed(FcpMessage receivedMessage) {
+       public GetFailed(FcpMessage receivedMessage) {
                super(receivedMessage);
        }
 
index 3419860..0a84acf 100644 (file)
@@ -49,7 +49,14 @@ public class GetNode extends FcpMessage {
         *            <code>true</code> to include volatile data in the noderef
         */
        public GetNode(Boolean giveOpennetRef, Boolean withPrivate, Boolean withVolatile) {
+               this(null, giveOpennetRef, withPrivate, withVolatile);
+       }
+
+       public GetNode(String identifier, Boolean giveOpennetRef, Boolean withPrivate, Boolean withVolatile) {
                super("GetNode");
+               if (identifier != null) {
+                       setField("Identifier", identifier);
+               }
                if (giveOpennetRef != null) {
                        setField("GiveOpennetRef", String.valueOf(giveOpennetRef));
                }
index 8ad5392..12e446e 100644 (file)
@@ -26,20 +26,20 @@ package net.pterodactylus.fcp;
  */
 public class GetPluginInfo extends FcpMessage {
 
-       /**
-        * Creates a new “GetPluginInfo” message.
-        *
-        * @param pluginName
-        *            The name of the plugin
-        * @param identifier
-        *            The identifier of the request
-        */
-       public GetPluginInfo(String pluginName, String identifier) {
+       public GetPluginInfo(String identifier) {
                super("GetPluginInfo");
-               setField("PluginName", pluginName);
                setField("Identifier", identifier);
        }
 
+       public GetPluginInfo(String pluginName, String identifier) {
+               this(identifier);
+               setField("PluginName", pluginName);
+       }
+
+       public void setPluginName(String pluginName) {
+               setField("PluginName", pluginName);
+       }
+
        /**
         * Sets whether detailed information about the plugin is wanted.
         *
index 5ce6f4a..bd28d67 100644 (file)
@@ -33,7 +33,7 @@ public class IdentifierCollision extends BaseMessage implements Identifiable {
         * @param receivedMessage
         *            The received message
         */
-       IdentifierCollision(FcpMessage receivedMessage) {
+       public IdentifierCollision(FcpMessage receivedMessage) {
                super(receivedMessage);
        }
 
diff --git a/src/main/java/net/pterodactylus/fcp/Key.java b/src/main/java/net/pterodactylus/fcp/Key.java
new file mode 100644 (file)
index 0000000..f16b752
--- /dev/null
@@ -0,0 +1,20 @@
+package net.pterodactylus.fcp;
+
+/**
+ * Non-validating wrapper around a Freenet key.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class Key {
+
+       private final String key;
+
+       public Key(String key) {
+               this.key = key;
+       }
+
+       public String getKey() {
+               return key;
+       }
+
+}
index e96a389..2984e6c 100644 (file)
@@ -35,7 +35,14 @@ public class ListPeer extends FcpMessage {
         *            The identifier of the node to get details about
         */
        public ListPeer(String nodeIdentifier) {
+               this(null, nodeIdentifier);
+       }
+
+       public ListPeer(String identifier, String nodeIdentifier) {
                super("ListPeer");
+               if (identifier != null) {
+                       setField("Identifier", identifier);
+               }
                setField("NodeIdentifier", nodeIdentifier);
        }
 
index 82e3399..9080830 100644 (file)
@@ -38,4 +38,9 @@ public class ListPeerNotes extends FcpMessage {
                setField("NodeIdentifier", nodeIdentifier);
        }
 
+       public ListPeerNotes(String identifier, String nodeIdentifier) {
+               this(nodeIdentifier);
+               setField("Identifier", identifier);
+       }
+
 }
diff --git a/src/main/java/net/pterodactylus/fcp/LoadPlugin.java b/src/main/java/net/pterodactylus/fcp/LoadPlugin.java
new file mode 100644 (file)
index 0000000..9eb2d2d
--- /dev/null
@@ -0,0 +1,47 @@
+package net.pterodactylus.fcp;
+
+/**
+ * The “LoadPlugin” message is used to load a plugin.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class LoadPlugin extends FcpMessage {
+
+       public enum UrlType {
+
+               OFFICIAL,
+               FILE,
+               FREENET,
+               URL
+
+       }
+
+       public enum OfficialSource {
+
+               FREENET,
+               HTTPS
+
+       }
+
+       public LoadPlugin(String identifier) {
+               super("LoadPlugin");
+               setField("Identifier", identifier);
+       }
+
+       public void setPluginUrl(String pluginUrl) {
+               setField("PluginURL", pluginUrl);
+       }
+
+       public void setUrlType(UrlType urlType) {
+               setField("URLType", urlType.toString().toLowerCase());
+       }
+
+       public void setStore(boolean store) {
+               setField("Store", String.valueOf(store));
+       }
+
+       public void setOfficialSource(OfficialSource officialSource) {
+               setField("OfficialSource", officialSource.toString().toLowerCase());
+       }
+
+}
index 412b818..687ee16 100644 (file)
@@ -32,6 +32,11 @@ public class ModifyConfig extends FcpMessage {
                super("ModifyConfig");
        }
 
+       public ModifyConfig(String identifier) {
+               this();
+               setField("Identifier", identifier);
+       }
+
        /**
         * Sets the option with the given name to the given value.
         *
index dfc5aa2..f1905e7 100644 (file)
@@ -25,32 +25,45 @@ package net.pterodactylus.fcp;
  */
 public class ModifyPeer extends FcpMessage {
 
-       /**
-        * Creates a new “ModifyPeer” request. All Boolean parameters may be null
-        * to not influence the current setting.
-        *
-        * @param nodeIdentifier
-        *            The identifier of the node, i.e. name, identity, or IP
-        *            address and port
-        * @param allowLocalAddresses
-        *            Whether to allow local addresses from this node
-        * @param disabled
-        *            Whether the node is disabled
-        * @param listenOnly
-        *            Whether your node should not try to connect the node
-        */
+       public ModifyPeer(String identifier, String nodeIdentifier) {
+               super("ModifyPeer");
+               setField("Identifier", identifier);
+               setField("NodeIdentifier", nodeIdentifier);
+       }
+
+       @Deprecated
        public ModifyPeer(String nodeIdentifier, Boolean allowLocalAddresses, Boolean disabled, Boolean listenOnly) {
                super("ModifyPeer");
                setField("NodeIdentifier", nodeIdentifier);
                if (allowLocalAddresses != null) {
-                       setField("AllowLocalAddresses", String.valueOf(allowLocalAddresses));
+                       setAllowLocalAddresses(allowLocalAddresses);
                }
                if (disabled != null) {
-                       setField("IsDisabled", String.valueOf(disabled));
+                       setEnabled(!disabled);
                }
                if (listenOnly != null) {
-                       setField("IsListenOnly", String.valueOf(listenOnly));
+                       setListenOnly(listenOnly);
                }
        }
 
+       public void setAllowLocalAddresses(boolean allowLocalAddresses) {
+               setField("AllowLocalAddresses", String.valueOf(allowLocalAddresses));
+       }
+
+       public void setEnabled(boolean enabled) {
+               setField("IsDisabled", String.valueOf(!enabled));
+       }
+
+       public void setListenOnly(boolean listenOnly) {
+               setField("IsListenOnly", String.valueOf(listenOnly));
+       }
+
+       public void setBurstOnly(boolean burstOnly) {
+               setField("IsBurstOnly", String.valueOf(burstOnly));
+       }
+
+       public void setIgnoreSource(boolean ignoreSource) {
+               setField("IgnoreSourcePort", String.valueOf(ignoreSource));
+       }
+
 }
index 6fcc088..c7338ff 100644 (file)
@@ -18,6 +18,8 @@
 
 package net.pterodactylus.fcp;
 
+import com.google.common.base.Charsets;
+
 /**
  * The “ModifyPeerNote” command modifies a peer note.
  *
@@ -25,25 +27,28 @@ package net.pterodactylus.fcp;
  */
 public class ModifyPeerNote extends FcpMessage {
 
-       /**
-        * Creates a new “ModifyPeerNote” request that changes peer note of the
-        * given type and node to the given text.
-        *
-        * @see PeerNote
-        * @param nodeIdentifier
-        *            The identifier of the node, i.e. name, identity, or IP
-        *            address and port
-        * @param noteText
-        *            The base64-encoded text
-        * @param peerNoteType
-        *            The type of the note to change, possible values are only
-        *            {@link PeerNote#TYPE_PRIVATE_PEER_NOTE} at the moment
-        */
+       private static final FreenetBase64 BASE64_ENCODER = new FreenetBase64();
+
+       public ModifyPeerNote(String identifier, String nodeIdentifier) {
+               super("ModifyPeerNote");
+               setField("Identifier", identifier);
+               setField("NodeIdentifier", nodeIdentifier);
+       }
+
+       @Deprecated
        public ModifyPeerNote(String nodeIdentifier, String noteText, int peerNoteType) {
-               super("ModifyPeer");
+               super("ModifyPeerNote");
                setField("NodeIdentifier", nodeIdentifier);
                setField("NoteText", noteText);
                setField("PeerNoteType", String.valueOf(peerNoteType));
        }
 
+       public void setNoteText(String noteText) {
+               setField("NoteText", BASE64_ENCODER.encode(noteText.getBytes(Charsets.UTF_8)));
+       }
+
+       public void setPeerNoteType(PeerNoteType peerNoteType) {
+               setField("PeerNoteType", peerNoteType.toString());
+       }
+
 }
index f73bbd5..5800172 100644 (file)
@@ -34,7 +34,7 @@ public class NodeData extends BaseMessage {
         * @param receivedMessage
         *            The received message
         */
-       NodeData(FcpMessage receivedMessage) {
+       public NodeData(FcpMessage receivedMessage) {
                super(receivedMessage);
                nodeRef = new NodeRef(receivedMessage);
        }
index 7409d9b..32a4e33 100644 (file)
@@ -31,7 +31,7 @@ public class NodeHello extends BaseMessage {
         * @param receivedMessage
         *            The received FCP message
         */
-       NodeHello(FcpMessage receivedMessage) {
+       public NodeHello(FcpMessage receivedMessage) {
                super(receivedMessage);
        }
 
index df1c8f0..72925cb 100644 (file)
@@ -36,7 +36,7 @@ public class Peer extends BaseMessage implements Identifiable {
         * @param receivedMessage
         *            The received message
         */
-       Peer(FcpMessage receivedMessage) {
+       public Peer(FcpMessage receivedMessage) {
                super(receivedMessage);
        }
 
index 67cdfa6..034e40f 100644 (file)
@@ -18,6 +18,8 @@
 
 package net.pterodactylus.fcp;
 
+import com.google.common.base.Charsets;
+
 /**
  * The “PeerNote” message contains a private note that has been entered for a
  * darknet peer.
@@ -26,6 +28,8 @@ package net.pterodactylus.fcp;
  */
 public class PeerNote extends BaseMessage {
 
+       private static final FreenetBase64 BASE64_DECODER = new FreenetBase64();
+
        /** The type for base64 encoded peer notes. */
        public static final int TYPE_PRIVATE_PEER_NOTE = 1;
 
@@ -35,7 +39,7 @@ public class PeerNote extends BaseMessage {
         * @param receivedMessage
         *            The received message
         */
-       PeerNote(FcpMessage receivedMessage) {
+       public PeerNote(FcpMessage receivedMessage) {
                super(receivedMessage);
        }
 
@@ -54,7 +58,7 @@ public class PeerNote extends BaseMessage {
         * @return The note text
         */
        public String getNoteText() {
-               return getField("NoteText");
+               return new String(BASE64_DECODER.decode(getField("NoteText")), Charsets.UTF_8);
        }
 
        /**
diff --git a/src/main/java/net/pterodactylus/fcp/PeerNoteType.java b/src/main/java/net/pterodactylus/fcp/PeerNoteType.java
new file mode 100644 (file)
index 0000000..7ebede3
--- /dev/null
@@ -0,0 +1,23 @@
+package net.pterodactylus.fcp;
+
+/**
+ * All possible peer note types.
+ *
+ * @author <a href="mailto:bombe@freenetproject.org">David ‘Bombe’ Roden</a>
+ */
+public enum PeerNoteType {
+
+       PRIVATE_DARKNET_COMMENT(1);
+
+       private int value;
+
+       PeerNoteType(int value) {
+               this.value = value;
+       }
+
+       @Override
+       public String toString() {
+               return String.valueOf(value);
+       }
+
+}
index 61aa08d..80da4b6 100644 (file)
@@ -31,7 +31,7 @@ public class PeerRemoved extends BaseMessage {
         * @param receivedMessage
         *            The received message
         */
-       PeerRemoved(FcpMessage receivedMessage) {
+       public PeerRemoved(FcpMessage receivedMessage) {
                super(receivedMessage);
        }
 
index c7bfe20..7fc70a9 100644 (file)
@@ -33,7 +33,7 @@ public class PersistentGet extends BaseMessage implements Identifiable {
         * @param receivedMessage
         *            The received message
         */
-       PersistentGet(FcpMessage receivedMessage) {
+       public PersistentGet(FcpMessage receivedMessage) {
                super(receivedMessage);
        }
 
index 2dc8213..f1114ac 100644 (file)
@@ -32,7 +32,7 @@ public class PersistentPut extends BaseMessage implements Identifiable {
         * @param receivedMessage
         *            The received message
         */
-       PersistentPut(FcpMessage receivedMessage) {
+       public PersistentPut(FcpMessage receivedMessage) {
                super(receivedMessage);
        }
 
index b68c84c..4b668b3 100644 (file)
@@ -34,7 +34,7 @@ public class PersistentPutDir extends BaseMessage implements Identifiable {
         * @param receivedMessage
         *            The received message
         */
-       PersistentPutDir(FcpMessage receivedMessage) {
+       public PersistentPutDir(FcpMessage receivedMessage) {
                super(receivedMessage);
        }
 
index f1d2371..5b02624 100644 (file)
@@ -33,7 +33,7 @@ public class PersistentRequestModified extends BaseMessage implements Identifiab
         * @param receivedMessage
         *            The received message
         */
-       PersistentRequestModified(FcpMessage receivedMessage) {
+       public PersistentRequestModified(FcpMessage receivedMessage) {
                super(receivedMessage);
        }
 
index c9ec826..4d15250 100644 (file)
@@ -33,7 +33,7 @@ public class PersistentRequestRemoved extends BaseMessage implements Identifiabl
         * @param receivedMessage
         *            The received message
         */
-       PersistentRequestRemoved(FcpMessage receivedMessage) {
+       public PersistentRequestRemoved(FcpMessage receivedMessage) {
                super(receivedMessage);
        }
 
index fbce581..bf11be8 100644 (file)
@@ -31,7 +31,7 @@ public class PluginInfo extends BaseMessage implements Identifiable {
         * @param receivedMessage
         *            The received message
         */
-       PluginInfo(FcpMessage receivedMessage) {
+       public PluginInfo(FcpMessage receivedMessage) {
                super(receivedMessage);
        }
 
@@ -60,7 +60,7 @@ public class PluginInfo extends BaseMessage implements Identifiable {
         * @return The original URI of the plugin
         */
        public String getOriginalURI() {
-               return getField("OriginalUri");
+               return getField("OriginUri");
        }
 
        /**
@@ -70,7 +70,18 @@ public class PluginInfo extends BaseMessage implements Identifiable {
         *         otherwise
         */
        public boolean isStarted() {
-               return Boolean.valueOf("Started");
+               return Boolean.valueOf(getField("Started"));
        }
 
+       public boolean isTalkable() {
+               return Boolean.valueOf(getField("IsTalkable"));
+       }
+
+       public String getVersion() {
+               return getField("Version");
+       }
+
+       public String getLongVersion() {
+               return getField("LongVersion");
+       }
 }
diff --git a/src/main/java/net/pterodactylus/fcp/PluginRemoved.java b/src/main/java/net/pterodactylus/fcp/PluginRemoved.java
new file mode 100644 (file)
index 0000000..7492954
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * jFCPlib - PluginInfo.java - Copyright © 2008 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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+package net.pterodactylus.fcp;
+
+/**
+ * The “PluginRemoved” message is a reply to the {@link RemovePlugin} request.
+ *
+ * @author David ‘Bombe’ Roden &lt;bombe@freenetproject.org&gt;
+ */
+public class PluginRemoved extends BaseMessage implements Identifiable {
+
+       /**
+        * Creates a new “PluginRemoved” message that wraps the received message.
+        *
+        * @param receivedMessage
+        *      The received message
+        */
+       public PluginRemoved(FcpMessage receivedMessage) {
+               super(receivedMessage);
+       }
+
+       /**
+        * Returns the name of the plugin.
+        *
+        * @return The name of the plugin
+        */
+       public String getPluginName() {
+               return getField("PluginName");
+       }
+
+       /**
+        * Returns the identifier of the request.
+        *
+        * @return The identifier of the request
+        */
+       @Override
+       public String getIdentifier() {
+               return getField("Identifier");
+       }
+
+}
index 8b7b510..80d8487 100644 (file)
@@ -31,7 +31,7 @@ public class ProtocolError extends BaseMessage {
         * @param receivedMessage
         *            The received message
         */
-       ProtocolError(FcpMessage receivedMessage) {
+       public ProtocolError(FcpMessage receivedMessage) {
                super(receivedMessage);
        }
 
index 8535bcb..7853d39 100644 (file)
@@ -38,7 +38,7 @@ public class PutFailed extends BaseMessage implements Identifiable {
         * @param receivedMessage
         *            The received message
         */
-       PutFailed(FcpMessage receivedMessage) {
+       public PutFailed(FcpMessage receivedMessage) {
                super(receivedMessage);
        }
 
index 767b4ad..c9867b0 100644 (file)
@@ -33,7 +33,7 @@ public class PutFetchable extends BaseMessage implements Identifiable {
         * @param receivedMessage
         *            The received message
         */
-       PutFetchable(FcpMessage receivedMessage) {
+       public PutFetchable(FcpMessage receivedMessage) {
                super(receivedMessage);
        }
 
index d8c4434..c5ee7fd 100644 (file)
@@ -32,7 +32,7 @@ public class PutSuccessful extends BaseMessage implements Identifiable {
         * @param receivedMessage
         *            The received message
         */
-       PutSuccessful(FcpMessage receivedMessage) {
+       public PutSuccessful(FcpMessage receivedMessage) {
                super(receivedMessage);
        }
 
diff --git a/src/main/java/net/pterodactylus/fcp/ReloadPlugin.java b/src/main/java/net/pterodactylus/fcp/ReloadPlugin.java
new file mode 100644 (file)
index 0000000..bcdcde9
--- /dev/null
@@ -0,0 +1,31 @@
+package net.pterodactylus.fcp;
+
+/**
+ * The “ReloadPlugin” message is used to reload a plugin.
+ *
+ * @author <a href="mailto:bombe@freenetproject.org">David ‘Bombe’ Roden</a>
+ */
+public class ReloadPlugin extends FcpMessage {
+
+       public ReloadPlugin(String identifier) {
+               super("ReloadPlugin");
+               setField("Identifier", identifier);
+       }
+
+       public void setPluginName(String pluginName) {
+               setField("PluginName", pluginName);
+       }
+
+       public void setMaxWaitTime(int maxWaitTime) {
+               setField("MaxWaitTime", String.valueOf(maxWaitTime));
+       }
+
+       public void setPurge(boolean purge) {
+               setField("Purge", String.valueOf(purge));
+       }
+
+       public void setStore(boolean store) {
+               setField("Store", String.valueOf(store));
+       }
+
+}
index 5eae728..3f867fe 100644 (file)
@@ -25,16 +25,15 @@ package net.pterodactylus.fcp;
  */
 public class RemovePeer extends FcpMessage {
 
-       /**
-        * Creates a new “RemovePeer” command that removes the given peer.
-        *
-        * @param nodeIdentifier
-        *            The identifier of the node, i.e. its name, identity, or IP
-        *            address and port pair
-        */
+       @Deprecated
        public RemovePeer(String nodeIdentifier) {
                super("RemovePeer");
                setField("NodeIdentifier", nodeIdentifier);
        }
 
+       public RemovePeer(String identifier, String nodeIdentifier) {
+               this(nodeIdentifier);
+               setField("Identifier", identifier);
+       }
+
 }
diff --git a/src/main/java/net/pterodactylus/fcp/RemovePlugin.java b/src/main/java/net/pterodactylus/fcp/RemovePlugin.java
new file mode 100644 (file)
index 0000000..44fa9a7
--- /dev/null
@@ -0,0 +1,27 @@
+package net.pterodactylus.fcp;
+
+/**
+ * The “RemovePlugin” message is used to remove a plugin.
+ *
+ * @author <a href="mailto:bombe@freenetproject.org">David ‘Bombe’ Roden</a>
+ */
+public class RemovePlugin extends FcpMessage {
+
+       public RemovePlugin(String identifier) {
+               super("RemovePlugin");
+               setField("Identifier", identifier);
+       }
+
+       public void setPluginName(String pluginName) {
+               setField("PluginName", pluginName);
+       }
+
+       public void setMaxWaitTime(int maxWaitTime) {
+               setField("MaxWaitTime", String.valueOf(maxWaitTime));
+       }
+
+       public void setPurge(boolean purge) {
+               setField("Purge", String.valueOf(purge));
+       }
+
+}
diff --git a/src/main/java/net/pterodactylus/fcp/RequestProgress.java b/src/main/java/net/pterodactylus/fcp/RequestProgress.java
new file mode 100644 (file)
index 0000000..2dcc109
--- /dev/null
@@ -0,0 +1,63 @@
+package net.pterodactylus.fcp;
+
+/**
+ * Progress information about a request.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class RequestProgress {
+
+       private final int total;
+       private final int required;
+       private final int failed;
+       private final int fatallyFailed;
+       private final long lastProgress;
+       private final int succeeded;
+       private final boolean finalizedTotal;
+       private final int minSuccessFetchBlocks;
+
+       public RequestProgress(int total, int required, int failed, int fatallyFailed, long lastProgress, int succeeded,
+               boolean finalizedTotal, int minSuccessFetchBlocks) {
+               this.total = total;
+               this.required = required;
+               this.failed = failed;
+               this.fatallyFailed = fatallyFailed;
+               this.lastProgress = lastProgress;
+               this.succeeded = succeeded;
+               this.finalizedTotal = finalizedTotal;
+               this.minSuccessFetchBlocks = minSuccessFetchBlocks;
+       }
+
+       public int getTotal() {
+               return total;
+       }
+
+       public int getRequired() {
+               return required;
+       }
+
+       public int getFailed() {
+               return failed;
+       }
+
+       public int getFatallyFailed() {
+               return fatallyFailed;
+       }
+
+       public long getLastProgress() {
+               return lastProgress;
+       }
+
+       public int getSucceeded() {
+               return succeeded;
+       }
+
+       public boolean isFinalizedTotal() {
+               return finalizedTotal;
+       }
+
+       public int getMinSuccessFetchBlocks() {
+               return minSuccessFetchBlocks;
+       }
+
+}
index 55b27e9..01a95f0 100644 (file)
@@ -32,7 +32,7 @@ public class SSKKeypair extends BaseMessage implements Identifiable {
         * @param receivedMessage
         *            The received message
         */
-       SSKKeypair(FcpMessage receivedMessage) {
+       public SSKKeypair(FcpMessage receivedMessage) {
                super(receivedMessage);
        }
 
index 5f4da24..69a3bf2 100644 (file)
@@ -32,7 +32,7 @@ public class SimpleProgress extends BaseMessage implements Identifiable {
         * @param receivedMessage
         *            The received message
         */
-       SimpleProgress(FcpMessage receivedMessage) {
+       public SimpleProgress(FcpMessage receivedMessage) {
                super(receivedMessage);
        }
 
@@ -99,6 +99,14 @@ public class SimpleProgress extends BaseMessage implements Identifiable {
                return Boolean.valueOf(getField("FinalizedTotal"));
        }
 
+       public long getLastProgress() {
+               return Long.valueOf(getField("LastProgress"));
+       }
+
+       public int getMinSuccessFetchBlocks() {
+               return Integer.valueOf(getField("MinSuccessFetchBlocks"));
+       }
+
        /**
         * Returns the identifier of the request.
         *
index 1fd44f1..3aac42c 100644 (file)
@@ -33,7 +33,7 @@ public class StartedCompression extends BaseMessage implements Identifiable {
         * @param receivedMessage
         *            The received message
         */
-       StartedCompression(FcpMessage receivedMessage) {
+       public StartedCompression(FcpMessage receivedMessage) {
                super(receivedMessage);
        }
 
index 6a18333..634d1de 100644 (file)
@@ -24,22 +24,35 @@ package net.pterodactylus.fcp;
  *
  * @author David ‘Bombe’ Roden &lt;bombe@freenetproject.org&gt;
  */
-public class SubscribeUSK extends FcpMessage {
+public class SubscribeUSK extends FcpMessage implements Identifiable {
 
-       /**
-        * Creates a new “SubscribeUSK” message.
-        *
-        * @param uri
-        *            The URI to watch for changes
-        * @param identifier
-        *            The identifier of the request
-        */
-       public SubscribeUSK(String uri, String identifier) {
+       public SubscribeUSK(String identifier) {
                super("SubscribeUSK");
-               setField("URI", uri);
                setField("Identifier", identifier);
        }
 
+       public SubscribeUSK(String uri, String identifier) {
+               this(identifier);
+               setField("URI", uri);
+       }
+
+       @Override
+       public String getIdentifier() {
+               return getField("Identifier");
+       }
+
+       public String getUri() {
+               return getField("URI");
+       }
+
+       public void setUri(String uri) {
+               setField("URI", uri);
+       }
+
+       public boolean isActive() {
+               return !Boolean.parseBoolean(getField("DontPoll"));
+       }
+
        /**
         * Sets whether updates for the USK are actively searched.
         *
@@ -52,4 +65,52 @@ public class SubscribeUSK extends FcpMessage {
                setField("DontPoll", String.valueOf(!active));
        }
 
+       public boolean isSparse() {
+               return Boolean.valueOf(getField("SparsePoll"));
+       }
+
+       public void setSparse(boolean sparse) {
+               setField("SparsePoll", String.valueOf(sparse));
+       }
+
+       public Priority getPriority() {
+               String priorityClass = getField("PriorityClass");
+               if (priorityClass != null) {
+                       return Priority.valueOf(priorityClass);
+               }
+               return Priority.bulkSplitfile;
+       }
+
+       public void setPriority(Priority priority) {
+               setField("PriorityClass", priority.toString());
+       }
+
+       public Priority getActivePriority() {
+               String priorityClass = getField("PriorityClassProgress");
+               if (priorityClass != null) {
+                       return Priority.valueOf(priorityClass);
+               }
+               return Priority.update;
+       }
+
+       public void setActivePriority(Priority activePriority) {
+               setField("PriorityClassProgress", activePriority.toString());
+       }
+
+       public boolean isRealTime() {
+               return Boolean.valueOf(getField("RealTimeFlag"));
+       }
+
+       public void setRealTime(boolean realTime) {
+               setField("RealTimeFlag", String.valueOf(realTime));
+       }
+
+       public boolean isIgnoreDateHints() {
+               return Boolean.valueOf(getField("IgnoreUSKDatehints"));
+       }
+
+       public void setIgnoreDateHints(boolean ignoreDateHints) {
+               setField("IgnoreUSKDatehints", String.valueOf(ignoreDateHints));
+       }
+
 }
diff --git a/src/main/java/net/pterodactylus/fcp/SubscribedUSK.java b/src/main/java/net/pterodactylus/fcp/SubscribedUSK.java
new file mode 100644 (file)
index 0000000..f4c5d4d
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * jFCPlib - SubscribedUSKUpdate.java - Copyright © 2008 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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+package net.pterodactylus.fcp;
+
+/**
+ * A “SubscribedUSK” message is sent when a {@link SubscribeUSK} was succesfully processed.
+ *
+ * @author David ‘Bombe’ Roden &lt;bombe@freenetproject.org&gt;
+ */
+public class SubscribedUSK extends BaseMessage implements Identifiable {
+
+       public SubscribedUSK(FcpMessage receivedMessage) {
+               super(receivedMessage);
+       }
+
+       @Override
+       public String getIdentifier() {
+               return getField("Identifier");
+       }
+
+       public String getURI() {
+               return getField("URI");
+       }
+
+       public boolean isDontPoll() {
+               return Boolean.parseBoolean(getField("DontPoll"));
+       }
+
+}
index d2e132d..21cd466 100644 (file)
@@ -36,7 +36,7 @@ public class SubscribedUSKUpdate extends BaseMessage implements Identifiable {
         * @param receivedMessage
         *            The received message
         */
-       SubscribedUSKUpdate(FcpMessage receivedMessage) {
+       public SubscribedUSKUpdate(FcpMessage receivedMessage) {
                super(receivedMessage);
        }
 
index bea91d9..0a66de7 100644 (file)
@@ -32,7 +32,7 @@ public class TestDDAComplete extends BaseMessage {
         * @param receivedMessage
         *            The received message
         */
-       TestDDAComplete(FcpMessage receivedMessage) {
+       public TestDDAComplete(FcpMessage receivedMessage) {
                super(receivedMessage);
        }
 
index 9764a02..9e2b6d4 100644 (file)
@@ -36,7 +36,7 @@ public class TestDDAReply extends BaseMessage {
         * @param receivedMessage
         *            The received message
         */
-       TestDDAReply(FcpMessage receivedMessage) {
+       public TestDDAReply(FcpMessage receivedMessage) {
                super(receivedMessage);
        }
 
index 2d6d2a4..b508e04 100644 (file)
@@ -56,6 +56,7 @@ public class TestDDAResponse extends FcpMessage {
         */
        public TestDDAResponse(String directory, String readContent) {
                super("TestDDAResponse");
+               setField("Directory", directory);
                if (readContent != null) {
                        setField("ReadContent", readContent);
                }
index 4939570..1b126f1 100644 (file)
@@ -33,7 +33,7 @@ public class URIGenerated extends BaseMessage implements Identifiable {
         * @param receivedMessage
         *            The received message
         */
-       URIGenerated(FcpMessage receivedMessage) {
+       public URIGenerated(FcpMessage receivedMessage) {
                super(receivedMessage);
        }
 
index af7b2f5..a0d0891 100644 (file)
@@ -33,7 +33,7 @@ public class UnknownNodeIdentifier extends BaseMessage {
         * @param receivedMessage
         *            The received message
         */
-       UnknownNodeIdentifier(FcpMessage receivedMessage) {
+       public UnknownNodeIdentifier(FcpMessage receivedMessage) {
                super(receivedMessage);
        }
 
diff --git a/src/main/java/net/pterodactylus/fcp/UnsubscribeUSK.java b/src/main/java/net/pterodactylus/fcp/UnsubscribeUSK.java
new file mode 100644 (file)
index 0000000..baadefb
--- /dev/null
@@ -0,0 +1,15 @@
+package net.pterodactylus.fcp;
+
+/**
+ * The “UnsubscribeUSK” message is used to cancel a {@link SubscribeUSK USK subscription}.
+ *
+ * @author <a href="mailto:bombe@freenetproject.org">David ‘Bombe’ Roden</a>
+ */
+public class UnsubscribeUSK extends FcpMessage {
+
+       public UnsubscribeUSK(String identifier) {
+               super("UnsubscribeUSK");
+               setField("Identifier", identifier);
+       }
+
+}
diff --git a/src/test/java/net/pterodactylus/fcp/ModifyPeerNoteTest.java b/src/test/java/net/pterodactylus/fcp/ModifyPeerNoteTest.java
new file mode 100644 (file)
index 0000000..f82e012
--- /dev/null
@@ -0,0 +1,28 @@
+package net.pterodactylus.fcp;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+
+import org.junit.Test;
+
+/**
+ * Unit test for {@link ModifyPeerNote}.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class ModifyPeerNoteTest {
+
+       private static final String IDENTIFIER = "identifier";
+       private static final String NODE_IDENTIFIER = "node_identifier";
+       private static final String ENCODED_NOTE_TEXT = "VWJlck5vZGUgKHVudGlsIEkgaGF2ZSByZWFsIHBlZXJzKQ==";
+       private static final String DECODED_NOTE_TEXT = "UberNode (until I have real peers)";
+
+       @Test
+       public void noteTextIsEncodedCorrectly() {
+           ModifyPeerNote modifyPeerNote = new ModifyPeerNote(IDENTIFIER, NODE_IDENTIFIER);
+               modifyPeerNote.setNoteText(DECODED_NOTE_TEXT);
+               assertThat(modifyPeerNote.getField("NoteText"), is(ENCODED_NOTE_TEXT));
+       }
+
+
+}
diff --git a/src/test/java/net/pterodactylus/fcp/PeerNoteTest.java b/src/test/java/net/pterodactylus/fcp/PeerNoteTest.java
new file mode 100644 (file)
index 0000000..ce73f4c
--- /dev/null
@@ -0,0 +1,23 @@
+package net.pterodactylus.fcp;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+
+import org.junit.Test;
+
+/**
+ * Unit test for {@link PeerNote}.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class PeerNoteTest {
+
+       @Test
+       public void peerNoteIsDecodedCorrectly() {
+               FcpMessage receivedMessage = new FcpMessage("PeerNote");
+               receivedMessage.setField("NoteText", "VWJlck5vZGUgKHVudGlsIEkgaGF2ZSByZWFsIHBlZXJzKQ==");
+               PeerNote peerNote = new PeerNote(receivedMessage);
+               assertThat(peerNote.getNoteText(), is("UberNode (until I have real peers)"));
+       }
+
+}