Hi,

The review of the FCP rewrite is a huge undertaking, so I’ll limit myself to 
the functional changes since the review of bertm.

To get only these, I filtered the commits by their commit messages[1] and 
removed anything which looked like a documentation change or purely stylistic 
changes.

As a result the number of line changes (removed + added) went down from 13834 
to 1211.

As first step I’ll purely paste the diff here (and attach it along with a 
htmlized version for people without diff highlighting).

@xor: Please have a look at the commits and check whether any important 
functional change is missing (if yes, please add it). Also please give us a 
6-line description of the comments from bertm in his review. We must be able to 
verify against that, and each one of us clicking each outdated comment on 
github is not a viable way to do that.

Best wishes,
Arne

[1]: hg log --template "{node} : {desc|firstline}\n" -r 
"6c438b4c279d0a671be6516cee34052c7c3d5101::29ba0908ee2a81afdfaa1ab369382e1ad892b726"
 | sed "s/.*JavaDoc.*//" | sed "s/.*TODO.*//" | sed "s/.*Organize.*//" | sed 
s/.*ocument.*// | sed s/.*explain.*// | sed s/.*spelling.*// | sed s/.*sort.*// 
| sed s/.*[Ii]ndent.*// | sed s/.*[Mm]erge.*// | sed s/.*[Mm]ove.*// | sed 
s/.*[Ee]xtract.*// | sed s/.*[Rr]ename.*// | cut -d : -f 1 | xargs hg export


# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1420557120 -3600
#      Tue Jan 06 16:12:00 2015 +0100
# Node ID 6c438b4c279d0a671be6516cee34052c7c3d5101
# Parent  754640ea02b7a7a8b2165aa759c5eb10eb02eff0
FCPPluginClient.send(): Improve readability

- Improve documentation for the codepath of delivering messages to
sendSynchronous() threads.
- Rename maybeDispatchMessageLocallyToSendSynchronousThread() to
dispatchMessageLocallyToSendSynchronousThreadIfExisting(). Thats more
uniform with the other dispatch functions since they now all are
prefixed with  "dispatch" , and the "IfExisting"  is more
self-explanatory than "maybe"  because it implies the condition upon
which it is done: If a sendSynchronous() thread exists.

diff -r 754640ea02b7 -r 6c438b4c279d 
src/freenet/clients/fcp/FCPPluginClient.java
--- a/src/freenet/clients/fcp/FCPPluginClient.java      Wed Dec 10 04:23:00 
2014 +0100
+++ b/src/freenet/clients/fcp/FCPPluginClient.java      Tue Jan 06 16:12:00 
2015 +0100
@@ -643,14 +643,23 @@
             : "We already decided that the message handler exists locally. "
             + "We should have only decided so if the handler is not null.";

-        // Since the message handler is determined to be local at this point, 
we now must check
-        // whether it is a blocking sendSynchronous() thread instead of a 
regular
-        // FredPluginFCPMessageHandler.
-        // sendSynchronous() does the following: It sends a message and then 
blocks its thread
-        // waiting for a message replying to it to arrive so it can return it 
to the caller.
-        // If the message we are processing here is a reply, it might be the 
one which a
-        // sendSynchronous() is waiting for.
-        if(maybeDispatchMessageLocallyToSendSynchronousThread(direction, 
message))
+        // The message handler is determined to be local at this point. There 
are two possible
+        // types of local message handlers:
+        // 1) An object provided by the server/client which implements 
FredPluginFCPMessageHandler.
+        //    The message is delivered by executing a callback on that object, 
with the message
+        //    as parameter.
+        // 2) A call to sendSynchronous() which is blocking because it is 
waiting for a reply
+        //    to the message it sent so it can return the reply message to the 
caller.
+        //    The reply message is delivered by passing it to the 
sendSynchronous() thread through
+        //    an internal table of this class.
+        // 
+        // The following function call checks for whether case 2 applies, and 
handles it if yes:
+        // If there is such a waiting sendSynchronous() thread, it delivers 
the message to it, and
+        // returns true, and we are done: By contract, messages are preferably 
delivered to
+        // sendSynchronous().
+        // If there was no sendSynchronous() thread, it returns false, and we 
must continue to
+        // handle case 1.
+        if(dispatchMessageLocallyToSendSynchronousThreadIfExisting(direction, 
message))
             return;

         // We now know that the message handler is not attached by network, 
and that it is not a
@@ -725,8 +734,9 @@
      *          An overview of how synchronous sends and especially their 
threading work internally
      *          is provided at the map which stores them.
      */
-    private boolean maybeDispatchMessageLocallyToSendSynchronousThread(final 
SendDirection direction,
-            final FCPPluginMessage message) {
+    private boolean dispatchMessageLocallyToSendSynchronousThreadIfExisting(
+            final SendDirection direction, final FCPPluginMessage message) {
+
         // Since the message handler is determined to be local at this point, 
we now must check
         // whether it is a blocking sendSynchronous() thread instead of a 
regular
         // FredPluginFCPMessageHandler.
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1420559434 -3600
#      Tue Jan 06 16:50:34 2015 +0100
# Node ID 53db2d8eab097abbb354db7f4ed641362addaecb
# Parent  6c438b4c279d0a671be6516cee34052c7c3d5101
FCPConnectionHandler: Add send() to replace public member variable usage

- Temporarily deprecate the function of the member variable which led to
public usage of it.
- Add documentation about the deprecation to tell people to replace it
with send().
- Also document the temporary character of the deprecation.

diff -r 6c438b4c279d -r 53db2d8eab09 
src/freenet/clients/fcp/FCPConnectionHandler.java
--- a/src/freenet/clients/fcp/FCPConnectionHandler.java Tue Jan 06 16:12:00 
2015 +0100
+++ b/src/freenet/clients/fcp/FCPConnectionHandler.java Tue Jan 06 16:50:34 
2015 +0100
@@ -166,7 +166,21 @@
         // TODO: When getting rid of the non-UUID connectionIdentifier, use 
UUID.randomUUID();
         this.connectionIdentifierUUID = UUID.nameUUIDFromBytes(identifier);
        }
-       
+
+    /**
+     * Queues the message for sending at the {@link 
FCPConnectionOutputHandler}.<br>
+     * <br>
+     * 
+     * ATTENTION: The function will return immediately before even trying to 
send the message, the
+     * message will be sent asynchronously.<br>
+     * As a consequence, this function not throwing does not give any 
guarantee whatsoever that the
+     * message will ever be sent.
+     */
+    @SuppressWarnings("deprecation")
+    public final void send(final FCPMessage message) {
+        outputHandler.queue(message);
+    }
+
        void start() {
                inputHandler.start();
                outputHandler.start();
diff -r 6c438b4c279d -r 53db2d8eab09 
src/freenet/clients/fcp/FCPConnectionOutputHandler.java
--- a/src/freenet/clients/fcp/FCPConnectionOutputHandler.java   Tue Jan 06 
16:12:00 2015 +0100
+++ b/src/freenet/clients/fcp/FCPConnectionOutputHandler.java   Tue Jan 06 
16:50:34 2015 +0100
@@ -119,6 +119,19 @@
                }
        }

+    /**
+     * @deprecated Use {@link FCPConnectionHandler#send(FCPMessage)} instead 
of using public
+     *             access to the member variable {@link 
FCPConnectionHandler#outputHandler} to call
+     *             this function here upon the outputHandler. In other words: 
Replace
+     *             <code>fcpConnectionHandler.outputHandler.queue(...)</code>
+     *             with <code>fcpConnectionHandler.send(...)</code><br>
+     *             TODO: The deprecation is merely to enforce people to stop 
using the said
+     *             member variable in a public way. The function itself is 
fine to stay. Once the
+     *             public usage has been replaced by the suggested way of 
using send(),  please make
+     *             the member variable {@link 
FCPConnectionHandler#outputHandler} private and remove
+     *             the deprecation at this function here.
+     */
+    @Deprecated
        public void queue(FCPMessage msg) {
                if(logDEBUG)
                        Logger.debug(this, "Queueing "+msg, new 
Exception("debug"));
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1420559621 -3600
#      Tue Jan 06 16:53:41 2015 +0100
# Node ID de6402f91d982b00bbce5fd982266dc6ee536933
# Parent  53db2d8eab097abbb354db7f4ed641362addaecb
FCPPluginClient: Don't use FCPConnectionHandler member variable

The replacement of queue() with send() is what is suggested at queue()'s
JavaDoc.

diff -r 53db2d8eab09 -r de6402f91d98 
src/freenet/clients/fcp/FCPPluginClient.java
--- a/src/freenet/clients/fcp/FCPPluginClient.java      Tue Jan 06 16:50:34 
2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginClient.java      Tue Jan 06 16:53:41 
2015 +0100
@@ -711,7 +711,7 @@
         if (clientConnection.isClosed())
             throw new IOException("Connection to client closed for " + this);

-        clientConnection.outputHandler.queue(new 
FCPPluginServerMessage(serverPluginName, message));
+        clientConnection.send(new FCPPluginServerMessage(serverPluginName, 
message));
     }

     /**
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1420565343 -3600
#      Tue Jan 06 18:29:03 2015 +0100
# Node ID 42790e12661341c6fac8a1e4e3365bfcdeb6796a
# Parent  d328a143bcec85e4e3369b357cadee9ced0f7d03
PluginManager.getFCPPlugin(): Explain deprecation

diff -r d328a143bcec -r 42790e126613 
src/freenet/pluginmanager/PluginManager.java
--- a/src/freenet/pluginmanager/PluginManager.java      Tue Jan 06 18:20:46 
2015 +0100
+++ b/src/freenet/pluginmanager/PluginManager.java      Tue Jan 06 18:29:03 
2015 +0100
@@ -938,7 +938,9 @@
         * look for a FCPPlugin with given classname
         * @param plugname
         * @return the plugin or null if not found
-     * @deprecated Use {@link #getPluginFCPServer(String)} instead.
+     * @deprecated The {@link FredPluginFCP} API, which this returns, was 
deprecated to be replaced
+     *             by {@link FredPluginFCPMessageHandler}. The equivalent 
function for the new API
+     *             is {link #getPluginFCPServer(String)}.
         */
     @Deprecated
        public FredPluginFCP getFCPPlugin(String plugname) {
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1420565858 -3600
#      Tue Jan 06 18:37:38 2015 +0100
# Node ID 69be82200079f159c0cf6771987eeb69a3fc7b91
# Parent  6f0719590f85a66a5dce254ed5b7fcc73a79697b
PluginManager.getFCPPlugin(): Explain how to finish the deprecation

diff -r 6f0719590f85 -r 69be82200079 
src/freenet/pluginmanager/PluginManager.java
--- a/src/freenet/pluginmanager/PluginManager.java      Tue Jan 06 18:33:02 
2015 +0100
+++ b/src/freenet/pluginmanager/PluginManager.java      Tue Jan 06 18:37:38 
2015 +0100
@@ -939,8 +939,13 @@
         * @param plugname
         * @return the plugin or null if not found
      * @deprecated The {@link FredPluginFCP} API, which this returns, was 
deprecated to be replaced
-     *             by {@link 
FredPluginFCPMessageHandler.ServerSideFCPMessageHandler}. The
-     *             equivalent function for the new API is {link 
#getPluginFCPServer(String)}.
+     *             by {@link 
FredPluginFCPMessageHandler.ServerSideFCPMessageHandler}.
+     *             Plugin authors should implement the new interface instead 
of the old,
+     *             and this codepath to support plugins which implement the 
old interface should
+     *             be removed one day. No new code will be needed then: The 
code to use the 
+     *             new interface already exists in its own codepath - the 
equivalent function for
+     *             the new API is {link #getPluginFCPServer(String)}, and it 
is already being used
+     *             automatically for plugins which implement it.
         */
     @Deprecated
        public FredPluginFCP getFCPPlugin(String plugname) {
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1420833646 -3600
#      Fri Jan 09 21:00:46 2015 +0100
# Node ID a3b255be89e56da622d9c6c14efdbd19e04caee6
# Parent  8bbde4c2a2db3017fb0ff186e1c22ade08815abc
FCPPluginMessage.constructRawMessage(): Trim visibility

diff -r 8bbde4c2a2db -r a3b255be89e5 
src/freenet/clients/fcp/FCPPluginMessage.java
--- a/src/freenet/clients/fcp/FCPPluginMessage.java     Fri Jan 09 20:56:17 
2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginMessage.java     Fri Jan 09 21:00:46 
2015 +0100
@@ -294,7 +294,7 @@
      * See the JavaDoc of the member variables with the same name as the 
parameters for an
      * explanation of the parameters.<br>
      */
-    public static FCPPluginMessage constructRawMessage(ClientPermissions 
permissions,
+    static FCPPluginMessage constructRawMessage(ClientPermissions permissions,
             String identifier, SimpleFieldSet params, Bucket data, Boolean 
success,
             String errorCode, String errorMessage) {

# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1420835780 -3600
#      Fri Jan 09 21:36:20 2015 +0100
# Node ID d932dec809fd97d223ae73c3f58b7c69f4750576
# Parent  a424a96cb813df6751f7dc5f389bb9643f854680
FCPPluginClient.isServerDead(): Trim visibility

diff -r a424a96cb813 -r d932dec809fd 
src/freenet/clients/fcp/FCPPluginClient.java
--- a/src/freenet/clients/fcp/FCPPluginClient.java      Fri Jan 09 21:31:48 
2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginClient.java      Fri Jan 09 21:36:20 
2015 +0100
@@ -220,7 +220,7 @@
      *         a generic class WeakValueMap from that one and use to to power 
both the existing
      *         class and the one which deals with this variable here.
      * </p>
-     * @see #isServerDead() Public interface function to check whether the 
WeakReference is nulled.
+     * @see #isServerDead() Use isServerDead() to check whether this 
WeakReference is nulled.
      */
     private final WeakReference<ServerSideFCPMessageHandler> server;

@@ -475,6 +475,12 @@
     }

     /**
+     * ATTENTION: Only for internal use in {@link 
FCPConnectionHandler#getPluginClient(String)}.<br>
+     * Server / client code should always {@link #send(SendDirection, 
FCPPluginMessage)} messages
+     * to check whether the connection is alive. (To ensure that the 
implementation of this class
+     * could safely be changed to allow the server to be attached by network 
instead of always
+     * running locally in the same node as it currently is.)
+     * 
      * @return <p>True if the server plugin has been unloaded. Once this 
returns true, this
      *         FCPPluginClient <b>cannot</b> be repaired, even if the server 
plugin is loaded again.
      *         Then you should discard this client and create a fresh one.</p>
@@ -486,7 +492,7 @@
      *         is alive merely an indication, true / server is dead as the 
definite truth.<br>
      *         If you need to validate a connection to be alive, send periodic 
pings. </p>
      */
-    public boolean isServerDead() {
+    boolean isServerDead() {
         return server.get() == null;
     }

# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1420837732 -3600
#      Fri Jan 09 22:08:52 2015 +0100
# Node ID e255017cc021aae2ee7ff7a773b7ad37343d37ea
# Parent  d932dec809fd97d223ae73c3f58b7c69f4750576
FCPPluginClient.getServerPluginName(): Trim visibility

The JavaDoc already labeled it as "for internal use"

diff -r d932dec809fd -r e255017cc021 
src/freenet/clients/fcp/FCPPluginClient.java
--- a/src/freenet/clients/fcp/FCPPluginClient.java      Fri Jan 09 21:36:20 
2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginClient.java      Fri Jan 09 22:08:52 
2015 +0100
@@ -470,7 +470,7 @@
      * The class name of the plugin to which this FCPPluginClient is connected.
      * @see This is for internal usage by {@link 
FCPConnectionHandler#getPluginClient(String)}.
      */
-    public String getServerPluginName() {
+    String getServerPluginName() {
         return serverPluginName;
     }

# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1420840915 -3600
#      Fri Jan 09 23:01:55 2015 +0100
# Node ID 7209339131a01c925783a1e2decf1b3e4d73fe66
# Parent  7a8d58eef9937aeeea0fe71ff477277362f30c72
FCPPluginConnection: Clarify that server is a plugin, client may not be

Also adapt JavaDoc to rename "Client" -> "Connection" for this section.
More adaption w.r.t. that will follow.

diff -r 7a8d58eef993 -r 7209339131a0 
src/freenet/clients/fcp/FCPPluginConnection.java
--- a/src/freenet/clients/fcp/FCPPluginConnection.java  Fri Jan 09 22:56:04 
2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginConnection.java  Fri Jan 09 23:01:55 
2015 +0100
@@ -15,7 +15,10 @@
 import freenet.support.api.Bucket;

 /**
- * <p>An FCP client communicating with a plugin running within fred.</p>
+ * An FCP connection between:<br>
+ * - a fred plugin which provides its services by a FCP server.<br>
+ * - a client application which uses those services. The client may be a 
plugin as well, or be
+ *   connected by a networked FCP connection.<br><br>
  * 
  * <h1>How to use this properly</h1><br>
  * 
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1420914720 -3600
#      Sat Jan 10 19:32:00 2015 +0100
# Node ID c54c14dbff2a00eb0097a252ed5768a12374f1c8
# Parent  c9d86a341c0d227a734ae0c344bb1a2991416c04
FCPPluginConnection: Add missing license header

diff -r c9d86a341c0d -r c54c14dbff2a 
src/freenet/clients/fcp/FCPPluginConnection.java
--- a/src/freenet/clients/fcp/FCPPluginConnection.java  Fri Jan 09 23:41:31 
2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginConnection.java  Sat Jan 10 19:32:00 
2015 +0100
@@ -1,3 +1,6 @@
+/* This code is part of Freenet. It is distributed under the GNU General
+ * Public License, version 2 (or at your option any later version). See
+ * http://www.gnu.org/ for further details of the GPL. */
 package freenet.clients.fcp;

 import java.io.IOException;
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1420917113 -3600
#      Sat Jan 10 20:11:53 2015 +0100
# Node ID 1824423b2d8a13424ab19e9d11edbeca7343dfe4
# Parent  4a46dadc19d0d87833799846d648168327bfe541
FCPPluginConnection.send(): Fix "synchronousSend()" function name mixup

diff -r 4a46dadc19d0 -r 1824423b2d8a 
src/freenet/clients/fcp/FCPPluginConnection.java
--- a/src/freenet/clients/fcp/FCPPluginConnection.java  Sat Jan 10 20:09:35 
2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginConnection.java  Sat Jan 10 20:11:53 
2015 +0100
@@ -107,16 +107,16 @@
      * SendDirection, FCPPluginMessage, long)}:<br>
      * - It may return <b>before</b> the message has been sent.<br>
      *   The message sending happens in another thread so this function can 
return immediately.<br>
-     *   In opposite to that, a synchronousSend() would wait for a reply to 
arrive, so once it
+     *   In opposite to that, a sendSynchronous() would wait for a reply to 
arrive, so once it
      *   returns, the message is guaranteed to have been sent.<br>
      * - The reply is delivered to your message handler {@link 
FredPluginFCPMessageHandler}. It will
      *   not be directly available to the thread which called this 
function.<br>
-     *   A synchronousSend() would return the reply to the caller.<br>
+     *   A sendSynchronous() would return the reply to the caller.<br>
      * - You have no guarantee whatsoever that the message will be 
delivered.<br>
-     *   A synchronousSend() will tell you that a reply was received, which 
guarantees that the
+     *   A sendSynchronous() will tell you that a reply was received, which 
guarantees that the
      *   message was delivered.<br>
      * - The order of arrival of messages is random.<br>
-     *   A synchronousSend() only returns after the message was delivered 
already, so by calling
+     *   A sendSynchronous() only returns after the message was delivered 
already, so by calling
      *   it multiple times in a row on the same thread, you would enforce the 
order of the
      *   messages arriving at the remote side.<br><br>
      * 
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1420920960 -3600
#      Sat Jan 10 21:16:00 2015 +0100
# Node ID 293ceea684646899e6658fdb82edf99bf21cfa13
# Parent  29d4a0d2b39e673173f28152e90a3c4105b8963d
FCPPluginConnection: Add getServerPluginName()

Already implemented in the interface's implementation FCPPluginClient. I
had previously not added it to the interface since I wanted to keep it
package-private and interfaces can only have public functions.
But I would prefer for the package's internal code to typify variables
by the interface and not by the implementation, so the interface needs
to have that function.

diff -r 29d4a0d2b39e -r 293ceea68464 
src/freenet/clients/fcp/FCPPluginClient.java
--- a/src/freenet/clients/fcp/FCPPluginClient.java      Sat Jan 10 21:10:08 
2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginClient.java      Sat Jan 10 21:16:00 
2015 +0100
@@ -408,11 +408,7 @@
         return id;
     }

-    /**
-     * The class name of the plugin to which this FCPPluginClient is connected.
-     * @see This is for internal usage by {@link 
FCPConnectionHandler#getPluginClient(String)}.
-     */
-    String getServerPluginName() {
+    @Override public String getServerPluginName() {
         return serverPluginName;
     }

diff -r 29d4a0d2b39e -r 293ceea68464 
src/freenet/clients/fcp/FCPPluginConnection.java
--- a/src/freenet/clients/fcp/FCPPluginConnection.java  Sat Jan 10 21:10:08 
2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginConnection.java  Sat Jan 10 21:16:00 
2015 +0100
@@ -360,4 +360,9 @@
     /** @return A verbose String containing the internal state. Useful for 
debug logs. */
     public String toString();

+    /**
+     * The class name of the plugin to which this FCPPluginConnection is 
connected.
+     * @see This is for internal usage by {@link 
FCPConnectionHandler#getPluginClient(String)}.
+     */
+    public String getServerPluginName();
 }
\ No newline at end of file
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1420924529 -3600
#      Sat Jan 10 22:15:29 2015 +0100
# Node ID 142f2abcd7ec60b0ef70389cab8e67456270f707
# Parent  ece7e2c466440261975c409b4edddf8d3fa64058
FCPPluginConnection.getServerPluginName(): Fix useless line wrap

diff -r ece7e2c46644 -r 142f2abcd7ec 
src/freenet/clients/fcp/FCPPluginConnection.java
--- a/src/freenet/clients/fcp/FCPPluginConnection.java  Sat Jan 10 21:24:28 
2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginConnection.java  Sat Jan 10 22:15:29 
2015 +0100
@@ -363,9 +363,8 @@
     /**
      * The class name of the FCP server plugin to which this 
FCPPluginConnection is connected.<br>
      * This is what was specified for the parameter <code>String 
pluginName</code> by the client
-     * when connecting by calling
-     * {@link PluginRespirator#connectToOtherPlugin(String, 
ClientSideFCPMessageHandler)}
-     * .
+     * when connecting by calling {@link 
PluginRespirator#connectToOtherPlugin(String,
+     * ClientSideFCPMessageHandler)}.
      */
     public String getServerPluginName();
 }
\ No newline at end of file
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1421060986 -3600
#      Mon Jan 12 12:09:46 2015 +0100
# Node ID ae4a097065b3ad9d33a0fea040cfeecb84fb60dd
# Parent  0cd24017f93dfcc44738eff80344e83e1b19ffc8
FCPPluginClient: Fix excessive line length

diff -r 0cd24017f93d -r ae4a097065b3 
src/freenet/clients/fcp/FCPPluginClient.java
--- a/src/freenet/clients/fcp/FCPPluginClient.java      Mon Jan 12 12:06:04 
2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginClient.java      Mon Jan 12 12:09:46 
2015 +0100
@@ -392,8 +392,8 @@
      * - {@link PluginRespirator#connectToOtherPlugin(String, 
ClientSideFCPMessageHandler)} can then
      *   be used for obtaining a FCPPluginClient instead of this constructor. 
This also is a
      *   function which is used in regular mode of operation.<br>
-     * - The aforementioned {@link 
PluginRespirator#getPluginConnectionByID(UUID)} will then work for
-     *   FCPPluginClients obtained through the connectToOtherPlugin().
+     * - The aforementioned {@link 
PluginRespirator#getPluginConnectionByID(UUID)} will then work
+     *   for FCPPluginClients obtained through the connectToOtherPlugin().
      */
     public static FCPPluginClient 
constructForUnitTest(ServerSideFCPMessageHandler server,
         ClientSideFCPMessageHandler client) {
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1421061337 -3600
#      Mon Jan 12 12:15:37 2015 +0100
# Node ID 29b36e8801298a170e1c99c9c419848a29094d07
# Parent  33564410d690044fc680d32e3d21c32639ae8d71
FCPPluginConnection: Sort functions by importance

diff -r 33564410d690 -r 29b36e880129 
src/freenet/clients/fcp/FCPPluginConnection.java
--- a/src/freenet/clients/fcp/FCPPluginConnection.java  Mon Jan 12 12:14:14 
2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginConnection.java  Mon Jan 12 12:15:37 
2015 +0100
@@ -88,12 +88,6 @@
 public interface FCPPluginConnection {

     /**
-     * @return A unique identifier among all FCPPluginConnections.
-     * @see The ID can be used with {@link 
PluginRespirator#getPluginConnectionByID(UUID)}.
-     */
-    public UUID getID();
-
-    /**
      * The send functions are fully symmetrical: They work the same way no 
matter whether client
      * is sending to server or server is sending to client.<br/>
      * Thus, to prevent us from having to duplicate the send functions, this 
enum specifies in which
@@ -356,8 +350,11 @@
         SendDirection direction, FCPPluginMessage message, long 
timeoutNanoSeconds)
             throws IOException, InterruptedException;

-    /** @return A verbose String containing the internal state. Useful for 
debug logs. */
-    public String toString();
+    /**
+     * @return A unique identifier among all FCPPluginConnections.
+     * @see The ID can be used with {@link 
PluginRespirator#getPluginConnectionByID(UUID)}.
+     */
+    public UUID getID();

     /**
      * The class name of the FCP server plugin to which this 
FCPPluginConnection is connected.<br>
@@ -366,4 +363,8 @@
      * ClientSideFCPMessageHandler)}.
      */
     public String getServerPluginName();
+
+    /** @return A verbose String containing the internal state. Useful for 
debug logs. */
+    public String toString();
+
 }
\ No newline at end of file
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1421260650 -3600
#      Wed Jan 14 19:37:30 2015 +0100
# Node ID 788be9e7cba7f9710f0238170c73b80eb06153c2
# Parent  d3cef1a22d8cb721113847a80c6b280a900c7e72
Fix missed "FCPPluginClient" -> "FCPPluginConnectionImpl" renaming

The "Client" -> "Connection" interface extraction + renaming is not
finished yet, as  some  places where usage of FCPPluginConnectionImpl
has to be replaced with FCPPluginConnection might still remain.
This merely fixes all remaining textual references of "FCPPluginClient"

diff -r d3cef1a22d8c -r 788be9e7cba7 
src/freenet/clients/fcp/FCPPluginConnectionImpl.java
--- a/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Wed Jan 14 
19:28:59 2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Wed Jan 14 
19:37:30 2015 +0100
@@ -123,7 +123,7 @@


     /**
-     * Unique identifier among all FCPPluginClients.
+     * Unique identifier among all {@link FCPPluginConnection}s and 
FCPPluginConnectionImpls
      * @see #getID()
      */
     private final UUID id = UUID.randomUUID();
@@ -394,7 +394,7 @@
      *   be used for obtaining a FCPPluginConnectionImpl instead of this 
constructor. This also is a
      *   function which is used in regular mode of operation.<br>
      * - The aforementioned {@link 
PluginRespirator#getPluginConnectionByID(UUID)} will then work
-     *   for FCPPluginClients obtained through the connectToOtherPlugin().
+     *   for FCPPluginConnectionImpls obtained through the 
connectToOtherPlugin().
      */
     public static FCPPluginConnectionImpl 
constructForUnitTest(ServerSideFCPMessageHandler server,
         ClientSideFCPMessageHandler client) {
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1421261915 -3600
#      Wed Jan 14 19:58:35 2015 +0100
# Node ID ec7dc79c251d2758ba519f5da880ecb78d008c8a
# Parent  aae324185eebed32e663508effc55aaa631f54f2
FCPConnectionHandler.getFCPPluginConnection(): Trim visibility

Only meant to be used by the package for message deployment and thus
doesn't have to be public.

diff -r aae324185eeb -r ec7dc79c251d 
src/freenet/clients/fcp/FCPConnectionHandler.java
--- a/src/freenet/clients/fcp/FCPConnectionHandler.java Wed Jan 14 19:44:32 
2015 +0100
+++ b/src/freenet/clients/fcp/FCPConnectionHandler.java Wed Jan 14 19:58:35 
2015 +0100
@@ -634,7 +634,7 @@
      * @throws PluginNotFoundException
      *     If the specified plugin is not loaded or does not provide an FCP 
server.
      */
-    public FCPPluginConnection getFCPPluginConnection(String serverPluginName)
+    FCPPluginConnection getFCPPluginConnection(String serverPluginName)
             throws PluginNotFoundException {

         // The suspected typical usage pattern of this function is that the 
great majority of calls
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1421266988 -3600
#      Wed Jan 14 21:23:08 2015 +0100
# Node ID 6362805419f753e3730965e28d2b9c68047c8f82
# Parent  022e936b8617482985c6c3cf8c6a065239293018
FCPPluginConnectionImpl: Use parent interface as type when sensible

Not complete yet, more similar commits to follow for this class.

diff -r 022e936b8617 -r 6362805419f7 
src/freenet/clients/fcp/FCPPluginConnectionImpl.java
--- a/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Wed Jan 14 
21:18:18 2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Wed Jan 14 
21:23:08 2015 +0100
@@ -59,14 +59,14 @@
  * - The {@link FCPConnectionInputHandler} uses {@link 
FCPMessage#create(String, SimpleFieldSet)}
  *   to parse the message and obtain the actual {@link 
FCPPluginClientMessage}.<br/>
  * - The {@link FCPPluginClientMessage} uses {@link 
FCPConnectionHandler#getFCPPluginConnection(
- *   String)} to obtain the FCPPluginConnectionImpl to the server.<br/>
- * - The {@link FCPPluginClientMessage} uses {@link 
FCPPluginConnectionImpl#send(SendDirection,
+ *   String)} to obtain the FCPPluginConnection to the server.<br/>
+ * - The {@link FCPPluginClientMessage} uses {@link 
FCPPluginConnection#send(SendDirection,
  *   FCPPluginMessage)} to send the message to the server plugin.<br/>
  * - The FCP server plugin handles the message at
  *   {@link 
ServerSideFCPMessageHandler#handlePluginFCPMessage(FCPPluginConnection,
  *   FCPPluginMessage)}.<br/>
- * - As each FCPPluginConnectionImpl object exists for the lifetime of a 
network connection, the FCP
- *   server plugin may store the UUID of the FCPPluginConnectionImpl and query 
it via
+ * - As each FCPPluginConnection object exists for the lifetime of a network 
connection, the FCP
+ *   server plugin may store the UUID of the FCPPluginConnection and query it 
via
  *   {@link PluginRespirator#getPluginConnectionByID(UUID)}. It can use this 
to send messages to the
  *   client application on its own, that is not triggered by any client 
messages.<br/>
  * </p>
@@ -76,29 +76,30 @@
  *   FredPluginFCPMessageHandler.ClientSideFCPMessageHandler)} to try to 
create a connection.<br/>
  * - The {@link PluginRespirator} uses {@link 
FCPServer#createFCPPluginConnectionForIntraNodeFCP(
  *   String, FredPluginFCPMessageHandler.ClientSideFCPMessageHandler)} to get a
- *   FCPPluginConnectionImpl.<br>
- * - The client plugin uses the send functions of the FCPPluginConnectionImpl. 
Those are the same as
+ *   FCPPluginConnection.<br>
+ * - The client plugin uses the send functions of the FCPPluginConnection. 
Those are the same as
  *   with networked FCP connections.<br/>
  * - The FCP server plugin handles the message at
  *   {@link 
ServerSideFCPMessageHandler#handlePluginFCPMessage(FCPPluginConnection,
  *   FCPPluginMessage)}. That is the same handler as with networked FCP 
connections.<br/>
- * - The client plugin keeps a strong reference to the FCPPluginConnectionImpl 
in memory as long as
+ * - The client plugin keeps a strong reference to the FCPPluginConnection in 
memory as long as
  *   it wants to keep the connection open.<br/>
  * - Same as with networked FCP connections, the FCP server plugin can store 
the UUID of the
- *   FCPPluginConnectionImpl and in the future re-obtain the connection by
+ *   FCPPluginConnection and in the future re-obtain the connection by
  *   {@link PluginRespirator#getPluginConnectionByID(UUID)}. It can use this 
to send messages to the
  *   client application on its own, that is not triggered by any client 
messages. <br/>
  * - Once the client plugin is done with the connection, it discards the 
strong reference to the
- *   FCPPluginConnectionImpl. Because the {@link FCPPluginConnectionTracker} 
monitors garbage
- *   collection of {@link FCPPluginConnectionImpl} objects, getting rid of all 
strong references to
- *   a {@link FCPPluginConnectionImpl} is sufficient as a disconnection 
mechanism.<br/>
+ *   FCPPluginConnection. Because the {@link FCPPluginConnectionTracker} 
monitors garbage
+ *   collection of FCPPluginConnection objects, getting rid of all strong 
references to a
+ *   FCPPluginConnection is sufficient as a disconnection mechanism.<br/>
  *   Thus, an intra-node client connection is considered as disconnected once 
the
- *   FCPPluginConnectionImpl is not strongly referenced by the client plugin 
anymore. If a server
- *   plugin then tries to obtain the client by its UUID again (via the 
aforementioned
+ *   FCPPluginConnection is not strongly referenced by the client plugin 
anymore. If a server
+ *   plugin then tries to obtain the client connection by its UUID again (via 
the aforementioned
  *   {@link PluginRespirator#getPluginConnectionByID(UUID)}, the get will 
fail. So if the server
- *   plugin stores client UUIDs, it needs no special disconnection mechanism 
except for periodically
- *   trying to send a message to each client. Once obtaining the client by its 
UUID fails, or
- *   sending the message fails, the server can opportunistically purge the 
UUID from its database.
+ *   plugin stores connection UUIDs, it needs no special disconnection 
mechanism except for
+ *   periodically trying to send a message to each client. Once obtaining the 
client connection by
+ *   its UUID fails, or sending the message fails, the server can 
opportunistically purge the UUID
+ *   from its database.
  *   <br/>This mechanism also works for networked FCP.<br>
  * </p></p>
  */
@@ -391,10 +392,10 @@
      * - As loading a plugin by JAR is the same mode of operation as with a 
regular node,
      *   there will be a PluginRespirator available to it.<br>
      * - {@link PluginRespirator#connectToOtherPlugin(String, 
ClientSideFCPMessageHandler)} can then
-     *   be used for obtaining a FCPPluginConnectionImpl instead of this 
constructor. This also is the
+     *   be used for obtaining a FCPPluginConnection instead of this 
constructor. This also is the
      *   function to obtain a FCPPluginConnection which is used in regular 
mode of operation.<br>
      * - The aforementioned {@link 
PluginRespirator#getPluginConnectionByID(UUID)} will then work
-     *   for FCPPluginConnectionImpls obtained through the 
connectToOtherPlugin().
+     *   for FCPPluginConnections obtained through the connectToOtherPlugin().
      */
     public static FCPPluginConnectionImpl 
constructForUnitTest(ServerSideFCPMessageHandler server,
         ClientSideFCPMessageHandler client) {
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1421270478 -3600
#      Wed Jan 14 22:21:18 2015 +0100
# Node ID 7d91a4958bb358dd1926a92f62c0394231a36531
# Parent  9d1d0bc056dd2234d6aaf8b8060cddc286a7ed91
FCPPluginConnectionImpl: Catch Error thrown by message handlers

We should assume plugins to be buggy, and thus be conservative about
catching.

diff -r 9d1d0bc056dd -r 7d91a4958bb3 
src/freenet/clients/fcp/FCPPluginConnectionImpl.java
--- a/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Wed Jan 14 
21:49:33 2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Wed Jan 14 
22:21:18 2015 +0100
@@ -668,8 +668,15 @@
                 FCPPluginMessage reply = null;

                 try {
-                    reply = messageHandler.handlePluginFCPMessage(
-                        FCPPluginConnectionImpl.this, message);
+                    try {
+                        reply = messageHandler.handlePluginFCPMessage(
+                            FCPPluginConnectionImpl.this, message);
+                    } catch(Error e) {
+                        // TODO: Code quality: This is a workaround for Java 6 
not having
+                        // "catch(RuntimeException | Error e)". Once we are on 
Java 7, remove this
+                        // catch() block, and catch both types with the 
catch() block below.
+                        throw new RuntimeException(e);
+                    }
                 } catch(RuntimeException e) {
                     // The message handler is a server or client 
implementation, and thus as third
                     // party code might have bugs. So we need to catch any 
RuntimeException here.
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1421270754 -3600
#      Wed Jan 14 22:25:54 2015 +0100
# Node ID d93a92b458fe2e54079538e8db796b15e6420d19
# Parent  7d91a4958bb358dd1926a92f62c0394231a36531
FCPPluginConnectionImpl: Fix wrong Throwable type in error messages

We also catch(Error e) above (and convert it into RuntimeException), so
saying that it throw a RuntimeException is wrong. Throwable is the
common parent type.

diff -r 7d91a4958bb3 -r d93a92b458fe 
src/freenet/clients/fcp/FCPPluginConnectionImpl.java
--- a/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Wed Jan 14 
22:21:18 2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Wed Jan 14 
22:25:54 2015 +0100
@@ -683,9 +683,8 @@
                     // Notice that this is not normal mode of operation: 
Instead of throwing,
                     // the JavaDoc requests message handlers to return a reply 
with success=false.

-                    String errorMessage = "FredPluginFCPMessageHandler threw"
-                        + " RuntimeException. See JavaDoc of its member 
interfaces for how signal"
-                        + " errors properly."
+                    String errorMessage = "FredPluginFCPMessageHandler threw."
+                        + " See JavaDoc of its member interfaces for how 
signal errors properly."
                         + " Client = " + FCPPluginConnectionImpl.this
                         + "; SendDirection = " + direction
                         + "; message = " + message;
@@ -699,7 +698,7 @@
                         // quickly instead of having to wait for the timeout 
because no reply
                         // arrives.
                         reply = 
FCPPluginMessage.constructReplyMessage(message, null, null, false,
-                            "InternalError", errorMessage + "; 
RuntimeException = " + e.toString());
+                            "InternalError", errorMessage + "; Throwable = " + 
e.toString());
                     }
                 }

# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1421271553 -3600
#      Wed Jan 14 22:39:13 2015 +0100
# Node ID 6e8823e16ad20f38b472062f4566b5e32025fc4d
# Parent  b381cf165d7ec36af3a461e36ebfd3a4d8f95e2a
FCPPluginConnectionImpl: Unify logging

Do it the same way as in the rest of the function

diff -r b381cf165d7e -r 6e8823e16ad2 
src/freenet/clients/fcp/FCPPluginConnectionImpl.java
--- a/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Wed Jan 14 
22:37:47 2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Wed Jan 14 
22:39:13 2015 +0100
@@ -725,7 +725,9 @@
                             messageHandler, "Fred did not receive a reply from 
the message "
                                           + "handler even though it was 
allowed to reply. "
                                           + "This would cause 
sendSynchronous() to timeout! "
-                                          + "Original message: " + message);
+                                          + " connection = " + 
FCPPluginConnectionImpl.this
+                                          + "; SendDirection = " + direction
+                                          + "; message = " + message);
                     }
                 }

# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1421271619 -3600
#      Wed Jan 14 22:40:19 2015 +0100
# Node ID 9280fa1593f0ccff425467fcdce7acc636a59fed
# Parent  6e8823e16ad20f38b472062f4566b5e32025fc4d
FCPPluginConnectionImpl: Use parent interface as type when sensible

Not complete yet, more similar commits to follow for this class

diff -r 6e8823e16ad2 -r 9280fa1593f0 
src/freenet/clients/fcp/FCPPluginConnectionImpl.java
--- a/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Wed Jan 14 
22:39:13 2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Wed Jan 14 
22:40:19 2015 +0100
@@ -779,7 +779,7 @@

             /** @return A suitable {@link String} for use as the name of this 
thread */
             @Override public String toString() {
-                // Don't use FCPPluginConnectionImpl.toString() as it would be 
too long to fit in
+                // Don't use FCPPluginConnection.toString() as it would be too 
long to fit in
                 // the thread list on the Freenet FProxy web interface.
                 return "FCPPluginConnection for " + serverPluginName;
             }
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1421336574 -3600
#      Thu Jan 15 16:42:54 2015 +0100
# Node ID 15fef97e809064eac67f5a6b3da16d82d2a09abd
# Parent  9280fa1593f0ccff425467fcdce7acc636a59fed
FCPPluginConnectionImpl.sendSynchronous(): Unify error message format

Also explain *what* timed out

diff -r 9280fa1593f0 -r 15fef97e8090 
src/freenet/clients/fcp/FCPPluginConnectionImpl.java
--- a/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Wed Jan 14 
22:40:19 2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Thu Jan 15 
16:42:54 2015 +0100
@@ -850,9 +850,10 @@
                     // Include the FCPPluginMessage in the Exception so the 
developer can determine
                     // whether it is an issue of the remote side taking a long 
time to execute
                     // for certain messages.
-                    throw new IOException("The synchronous call timed out for 
" + this + "; "
-                                        + "direction = " + direction + "; "
-                                        + "message = " + message);
+                    throw new IOException("sendSynchronous() timed out waiting 
for reply! "
+                        + " connection = " + FCPPluginConnectionImpl.this
+                        + "; SendDirection = " + direction
+                        + "; message = " + message);
                 }

                 // The thread which sets synchronousSend.reply to be non-null 
calls
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1421337107 -3600
#      Thu Jan 15 16:51:47 2015 +0100
# Node ID 6c5e581ec28a75fc217bcf7285e1c2c62fa5ec93
# Parent  15fef97e809064eac67f5a6b3da16d82d2a09abd
FCPPluginConnectionImpl.toString(): Add "server" member variable

diff -r 15fef97e8090 -r 6c5e581ec28a 
src/freenet/clients/fcp/FCPPluginConnectionImpl.java
--- a/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Thu Jan 15 
16:42:54 2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Thu Jan 15 
16:51:47 2015 +0100
@@ -890,7 +890,8 @@

     @Override
     public String toString() {
-        return "FCPPluginConnectionImpl (ID: " + id + "; server plugin: " + 
serverPluginName
+        return "FCPPluginConnectionImpl (ID: " + id + "; server class: " + 
serverPluginName
+             + "; server: " + (server != null ? server.get() : null)
              + "; client: " + client + "; clientConnection: " + 
clientConnection +  ")";
     }

# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1421337307 -3600
#      Thu Jan 15 16:55:07 2015 +0100
# Node ID 16fb9a043d1906f353530f6f0e23e9cd8e7229a9
# Parent  6c5e581ec28a75fc217bcf7285e1c2c62fa5ec93
FCPPluginConnectionImpl: Use parent interface as type when sensible

This completes those changes for this class.

diff -r 6c5e581ec28a -r 16fb9a043d19 
src/freenet/clients/fcp/FCPPluginConnectionImpl.java
--- a/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Thu Jan 15 
16:51:47 2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Thu Jan 15 
16:55:07 2015 +0100
@@ -427,7 +427,7 @@
      *         FCPPluginConnectionImpl <b>cannot</b> be repaired, even if the 
server plugin is
      *         loaded again. Then you should discard this client and create a 
fresh one.</p>
      * 
-     *         <p><b>ATTENTION:</b> Future implementations of {@link 
FCPPluginConnectionImpl} might
+     *         <p><b>ATTENTION:</b> Future implementations of {@link 
FCPPluginConnection} might
      *         allow the server plugin to reside in a different node, and only 
be attached by
      *         network. Due to the unreliability of network connections, then 
this function will not
      *         be able to reliably detect whether the server is dead.<br>
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1421445140 -3600
#      Fri Jan 16 22:52:20 2015 +0100
# Node ID 6e853b7efb00230b05545ec54b1074990934ebf3
# Parent  11e5dd8e4c0ff16bf40276645a69e1e290948f4c
FCPPluginConnection: Add send functions with default SendDirection

This marks the begin of branch
FCPPluginConnection-default-SendDirection, whose goal shall be to
implement those functions.

diff -r 11e5dd8e4c0f -r 6e853b7efb00 
src/freenet/clients/fcp/FCPPluginConnection.java
--- a/src/freenet/clients/fcp/FCPPluginConnection.java  Thu Jan 15 20:29:06 
2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginConnection.java  Fri Jan 16 22:52:20 
2015 +0100
@@ -9,6 +9,7 @@

 import freenet.pluginmanager.FredPluginFCPMessageHandler;
 import 
freenet.pluginmanager.FredPluginFCPMessageHandler.ClientSideFCPMessageHandler;
+import 
freenet.pluginmanager.FredPluginFCPMessageHandler.ServerSideFCPMessageHandler;
 import freenet.pluginmanager.PluginRespirator;
 import freenet.support.Logger;
 import freenet.support.Logger.LogLevel;
@@ -190,6 +191,31 @@
     public void send(SendDirection direction, FCPPluginMessage message) throws 
IOException;

     /**
+     * Same as {@link #send(SendDirection, FCPPluginMessage)} with the {@link 
SendDirection}
+     * parameter being the default direction.<br>
+     * <b>Please do read its JavaDoc as it contains a very precise 
specification how to use it and
+     * thereby also this function.</b><br><br>
+     * 
+     * The default direction is determined automatically depending on whether 
you are a client or
+     * server.<br><br>
+     * 
+     * You are acting as a client, and thus by default send to the server, 
when you obtain a
+     * FCPPluginConnection...:<br>
+     * - from the return value of
+     *   {@link PluginRespirator#connectToOtherPlugin(String, 
ClientSideFCPMessageHandler)}.<br>
+     * - as parameter to your message handler callback {@link 
ClientSideFCPMessageHandler#
+     *   handlePluginFCPMessage(FCPPluginConnection, 
FCPPluginMessage)}.<br><br>
+     * 
+     * You are acting as a server, and thus by default send to the client, 
when you obtain a
+     * FCPPluginConnection...:<br>
+     * - as parameter to your message handler callback {@link 
ServerSideFCPMessageHandler#
+     *   handlePluginFCPMessage(FCPPluginConnection, FCPPluginMessage)}.<br>
+     * - from the return value of {@link 
PluginRespirator#getPluginConnectionByID(UUID)}.<br>
+     */
+    public void send(FCPPluginMessage message) throws IOException;
+
+
+    /**
      * Can be used by both server and client implementations to send messages 
in a blocking
      * manner to each other.<br>
      * The messages sent by this function will be delivered to the message 
handler
@@ -352,6 +378,19 @@
             throws IOException, InterruptedException;

     /**
+     * Same as {@link #sendSynchronous(SendDirection, FCPPluginMessage, long)} 
with the
+     * {@link SendDirection} parameter being the default direction.<br>
+     * <b>Please do read its JavaDoc as it contains a very precise 
specification how to use it and
+     * thereby also this function.</b><br><br>
+     * 
+     * For an explanation of how the default send direction is determined, see
+     * {@link #send(FCPPluginMessage)}.
+     */
+    public FCPPluginMessage sendSynchronous(FCPPluginMessage message, long 
timeoutNanoSeconds)
+        throws IOException, InterruptedException;
+
+
+    /**
      * @return A unique identifier among all FCPPluginConnections.
      * @see The ID can be used with {@link 
PluginRespirator#getPluginConnectionByID(UUID)}.
      */
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1421450378 -3600
#      Sat Jan 17 00:19:38 2015 +0100
# Node ID ec7d03e9917e283ef16443ecaf86dea4ae2e04da
# Parent  6e853b7efb00230b05545ec54b1074990934ebf3
FCPPluginConnectionImpl: Add member class DefaultSendDirectionAdapter

Will be used to implement the send funtions which default to a specific
SendDirection.

diff -r 6e853b7efb00 -r ec7d03e9917e 
src/freenet/clients/fcp/FCPPluginConnectionImpl.java
--- a/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Fri Jan 16 
22:52:20 2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Sat Jan 17 
00:19:38 2015 +0100
@@ -889,6 +889,69 @@
         }
     }

+    /**
+     * Encapsulates a FCPPluginConnectionImpl object and a default {@link 
SendDirection} to
+     * implement the send functions which don't require a direction 
parameter:<br>
+     * - {@link FCPPluginConnection#send(FCPPluginMessage)}<br>
+     * - {@link FCPPluginConnection#sendSynchronous(FCPPluginMessage, 
long)}}<br><br>
+     * 
+     * An adapter is needed instead of storing this as a member variable in 
FCPPluginConnectionImpl
+     * because a single FCPPluginConnectionImpl object is handed out both to 
the the server AND the
+     * client which uses, and their default send direction will be 
different:<br>
+     * A server will want to send to the client by default, but the client 
will want to default to
+     * sending to the server.<br><br>
+     * 
+     * Is abstract and has two implementing child classes (to implement 
differing internal
+     * requirements, see {@link #getConnection()}):<br>
+     * - {@link SendToClientAdapter} for default direction {@link 
SendDirection#ToClient}.<br>
+     * - {@link SendToServerAdapter} for default direction {@link 
SendDirection#ToServer}.<br>
+     */
+    private abstract static class DefaultSendDirectionAdapter implements 
FCPPluginConnection {
+        
+        private final SendDirection defaultDirection;
+        
+        DefaultSendDirectionAdapter(SendDirection defaultDirection) {
+            this.defaultDirection = defaultDirection;
+        }
+        
+        /**
+         * Returns the encapsulated backend FCPPluginConnection which shall be 
used for sending.<br>
+         * <br>
+         * 
+         * Abstract because storage of a FCPPluginConnection object is 
different for servers and
+         * clients and thus must be implemented in separate child classes:<br>
+         * - Clients may and must store a FCPPluginConnection with a hard 
reference because a
+         *   connection is considered as closed once there is no more hard 
reference to it.<br>
+         *   Disconnection is detected by monitoring the FCPluginConnection 
for garbage collection.
+         *   <br>
+         * - Servers must store a FCPPluginConnection with a {@link 
WeakReference} (or always query
+         *   it by UUID from the node) to ensure that they will get garbage 
connected once the
+         *   client decides to disconnect by dropping all strong references.
+         */
+        protected abstract FCPPluginConnection getConnection() throws 
IOException;
+
+
+        @Override public void send(FCPPluginMessage message) throws 
IOException {
+            send(defaultDirection, message);
+        }
+
+        @Override public FCPPluginMessage sendSynchronous(FCPPluginMessage 
message,
+                long timeoutNanoSeconds) throws IOException, 
InterruptedException {
+            return sendSynchronous(defaultDirection, message, 
timeoutNanoSeconds);
+        }
+
+        @Override public void send(SendDirection direction, FCPPluginMessage 
message)
+                throws IOException {
+            getConnection().send(direction, message);
+        }
+
+        @Override public FCPPluginMessage sendSynchronous(SendDirection 
direction,
+                FCPPluginMessage message, long timeoutNanoSeconds)
+                    throws IOException, InterruptedException {
+            return getConnection().sendSynchronous(direction, message, 
timeoutNanoSeconds);
+        }
+    }
+
     @Override
     public String toString() {
         return "FCPPluginConnectionImpl (ID: " + id + "; server class: " + 
serverPluginName
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1421450797 -3600
#      Sat Jan 17 00:26:37 2015 +0100
# Node ID a22003ad422630d1bf85a7dca52011540aa3204d
# Parent  ec7d03e9917e283ef16443ecaf86dea4ae2e04da
FCPPluginConnectionImpl: Fix grammar typo

diff -r ec7d03e9917e -r a22003ad4226 
src/freenet/clients/fcp/FCPPluginConnectionImpl.java
--- a/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Sat Jan 17 
00:19:38 2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Sat Jan 17 
00:26:37 2015 +0100
@@ -897,7 +897,7 @@
      * 
      * An adapter is needed instead of storing this as a member variable in 
FCPPluginConnectionImpl
      * because a single FCPPluginConnectionImpl object is handed out both to 
the the server AND the
-     * client which uses, and their default send direction will be 
different:<br>
+     * client which use it, and their default send direction will be 
different:<br>
      * A server will want to send to the client by default, but the client 
will want to default to
      * sending to the server.<br><br>
      * 
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1421684302 -3600
#      Mon Jan 19 17:18:22 2015 +0100
# Node ID 15ce0a77c5cb872b617f7eede166df65f5b6b322
# Parent  a22003ad422630d1bf85a7dca52011540aa3204d
FCPPluginConnectionImpl: Add member class SendToClientAdapter

Implements DefaultSendDirectionAdapter with the direction of sending to
the client.
Not private since it will have to be used by the FCPServer. Explanation
will follow when committing that code.

diff -r a22003ad4226 -r 15ce0a77c5cb 
src/freenet/clients/fcp/FCPPluginConnectionImpl.java
--- a/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Sat Jan 17 
00:26:37 2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Mon Jan 19 
17:18:22 2015 +0100
@@ -952,6 +952,45 @@
         }
     }

+    /**
+     * Encapsulates a FCPPluginConnectionImpl object with a default {@link 
SendDirection} of
+     * {@link SendDirection#ToClient} to implement the send functions which 
don't require a
+     * direction parameter:<br>
+     * - {@link FCPPluginConnection#send(FCPPluginMessage)}<br>
+     * - {@link FCPPluginConnection#sendSynchronous(FCPPluginMessage, 
long)}}<br><br>
+     * 
+     * Must only be used by the server, not by the client: Clients must keep a 
strong reference to
+     * the connection to prevent its garbage collection (= disconnection), but 
this does not keep
+     * a strong reference.<br>
+     * See section "Disconnecting properly" at {@link 
PluginRespirator#connectToOtherPlugin(
+     * String, ClientSideFCPMessageHandler)}.
+     */
+    static final class SendToClientAdapter extends DefaultSendDirectionAdapter 
{
+
+        /** Is used to query the underlying FCPPluginConnectionImpl 
dynamically by its {@link UUID}
+         *  {@link #id} since this class, being aimed at being used by the 
server, may not keep a
+         *  strong reference to the connection to ensure that the client owns 
the power of purging
+         *  all strong references to it to cause disconnection. */
+        private final FCPPluginConnectionTracker tracker;
+        
+        /** The {@link FCPPluginConnection#getID()} of the underlying 
connection. */
+        private final UUID id;
+
+        SendToClientAdapter(FCPPluginConnectionTracker tracker, UUID 
connectionID) {
+            super(SendDirection.ToClient);
+            this.tracker = tracker;
+            this.id = connectionID;
+        }
+
+        @Override protected FCPPluginConnection getConnection() throws 
IOException {
+            return tracker.getConnection(id);
+        }
+
+        @Override public UUID getID() {
+            return id;
+        }
+    }
+
     @Override
     public String toString() {
         return "FCPPluginConnectionImpl (ID: " + id + "; server class: " + 
serverPluginName
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1421684716 -3600
#      Mon Jan 19 17:25:16 2015 +0100
# Node ID 60ebdf73fc98b420007852fb38dde69ae4557a76
# Parent  15ce0a77c5cb872b617f7eede166df65f5b6b322
FCPPluginConnectionImpl: Add member class SendToServerAdapter

Implements DefaultSendDirectionAdapter with the direction of sending
to the server.

diff -r 15ce0a77c5cb -r 60ebdf73fc98 
src/freenet/clients/fcp/FCPPluginConnectionImpl.java
--- a/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Mon Jan 19 
17:18:22 2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Mon Jan 19 
17:25:16 2015 +0100
@@ -991,6 +991,39 @@
         }
     }

+    /**
+     * Encapsulates a FCPPluginConnectionImpl object with a default {@link 
SendDirection} of
+     * {@link SendDirection#ToServer} to implement the send functions which 
don't require a
+     * direction parameter:<br>
+     * - {@link FCPPluginConnection#send(FCPPluginMessage)}<br>
+     * - {@link FCPPluginConnection#sendSynchronous(FCPPluginMessage, 
long)}}<br><br>
+     * 
+     * ATTENTION: Must only be used by the client, not by the server: Client 
disconnection is
+     * implemented by monitoring the garbage collection of their 
FCPPluginConnectionImpl objects
+     * - once the connection is not strong referenced anymore, it is 
considered as closed.
+     * As this class keeps a strong reference to the connection, if servers 
did use it, they would
+     * prevent client disconnection.<br>
+     * See section "Disconnecting properly" at {@link 
PluginRespirator#connectToOtherPlugin(
+     * String, ClientSideFCPMessageHandler)}.
+     */
+    private static final class SendToServerAdapter extends 
DefaultSendDirectionAdapter {
+
+        private final FCPPluginConnection parent;
+
+        SendToServerAdapter(FCPPluginConnectionImpl parent) {
+            super(SendDirection.ToServer);
+            this.parent = parent;
+        }
+
+        @Override protected FCPPluginConnection getConnection() {
+            return parent;
+        }
+
+        @Override public UUID getID() {
+            return parent.getID();
+        }
+    }
+
     @Override
     public String toString() {
         return "FCPPluginConnectionImpl (ID: " + id + "; server class: " + 
serverPluginName
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1421685975 -3600
#      Mon Jan 19 17:46:15 2015 +0100
# Node ID 9bc0180a40977468419e9ae3c8ec729d3d6ea9ca
# Parent  1e611fd6dbf22ef88c8fa0d0edc9ee3a2d01bb40
FCPPluginConnectionImpl: Add storage for DefaultSendDirectionAdapters

This also changes the factory functions
FCPPluginConnectionImpl.construct*() to automatically register the
connection at the FCPPluginConnectionTracker, which is more robust
anyway.

diff -r 1e611fd6dbf2 -r 9bc0180a4097 
src/freenet/clients/fcp/FCPPluginConnectionImpl.java
--- a/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Mon Jan 19 
17:27:18 2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Mon Jan 19 
17:46:15 2015 +0100
@@ -6,6 +6,7 @@
 import java.io.IOException;
 import java.lang.ref.ReferenceQueue;
 import java.lang.ref.WeakReference;
+import java.util.EnumMap;
 import java.util.TreeMap;
 import java.util.UUID;
 import java.util.concurrent.TimeUnit;
@@ -270,6 +271,17 @@
      */
     private final ReadWriteLock synchronousSendsLock = new 
ReentrantReadWriteLock();

+    /**
+     * A {@link DefaultSendDirectionAdapter} is an adapter which encapsulates a
+     * FCPPluginConnectionImpl object with a default {@link SendDirection} to 
implement the send
+     * functions which don't require a direction parameter:<br>
+     * - {@link FCPPluginConnection#send(FCPPluginMessage)}<br>
+     * - {@link FCPPluginConnection#sendSynchronous(FCPPluginMessage, 
long)}}<br><br>
+     *  
+     * For each possible {@link SendDirection}, this map keeps the responsible 
adapter. */
+    private final EnumMap<SendDirection, DefaultSendDirectionAdapter> 
defaultSendDirectionAdapters
+        = new EnumMap<SendDirection, 
DefaultSendDirectionAdapter>(SendDirection.class);
+

     /**
      * For being used by networked FCP connections:<br/>
@@ -278,12 +290,15 @@
      * The client is not running within the node, it is attached by network 
with a
      * {@link FCPConnectionHandler}.<br/>
      * 
-     * @see #constructForNetworkedFCP(Executor, PluginManager, String, 
FCPConnectionHandler)
+     * @see #constructForNetworkedFCP(FCPPluginConnectionTracker, Executor, 
PluginManager, String,
+     *      FCPConnectionHandler)
      *          The public interface to this constructor.
      */
-    private FCPPluginConnectionImpl(Executor executor, String serverPluginName,
-            ServerSideFCPMessageHandler serverPlugin, FCPConnectionHandler 
clientConnection) {
+    private FCPPluginConnectionImpl(FCPPluginConnectionTracker tracker, 
Executor executor,
+            String serverPluginName, ServerSideFCPMessageHandler serverPlugin,
+            FCPConnectionHandler clientConnection) {

+        assert(tracker != null);
         assert(executor != null);
         assert(serverPlugin != null);
         assert(serverPluginName != null);
@@ -294,6 +309,10 @@
         this.server = new 
WeakReference<ServerSideFCPMessageHandler>(serverPlugin);
         this.client = null;
         this.clientConnection = clientConnection;
+        this.defaultSendDirectionAdapters.put(SendDirection.ToServer,
+                new SendToServerAdapter(this));
+        this.defaultSendDirectionAdapters.put(SendDirection.ToClient,
+                new SendToClientAdapter(tracker, id));
     }

     /**
@@ -303,23 +322,24 @@
      * The client is not running within the node, it is attached by network 
with the given
      * {@link FCPConnectionHandler} clientConnection.<br/>
      * 
-     * <p>You <b>must</b> register any newly created connections at
-     * {@link 
FCPPluginConnectionTracker#registerConnection(FCPPluginConnection)} before 
handing
-     * them out to plugin code.</p>
+     * The returned connection is registered at the given {@link 
FCPPluginConnectionTracker}.
      */
-    static FCPPluginConnectionImpl constructForNetworkedFCP(Executor executor,
-            PluginManager serverPluginManager, String serverPluginName,
-            FCPConnectionHandler clientConnection)
+    static FCPPluginConnectionImpl 
constructForNetworkedFCP(FCPPluginConnectionTracker tracker,
+            Executor executor, PluginManager serverPluginManager,
+            String serverPluginName, FCPConnectionHandler clientConnection)
                 throws PluginNotFoundException {

+        assert(tracker != null);
         assert(executor != null);
         assert(serverPluginManager != null);
         assert(serverPluginName != null);
         assert(clientConnection != null);

-        return new FCPPluginConnectionImpl(executor,
+        FCPPluginConnectionImpl result = new FCPPluginConnectionImpl(tracker, 
executor,
             serverPluginName, 
serverPluginManager.getPluginFCPServer(serverPluginName),
             clientConnection);
+        tracker.registerConnection(result);
+        return result;
     }


@@ -332,12 +352,15 @@
      * The client's message handler is accessible as an implementor of
      * {@link ClientSideFCPMessageHandler}.<br>
      * 
-     * @see #constructForIntraNodeFCP(Executor, PluginManager, String, 
ClientSideFCPMessageHandler)
+     * @see #constructForIntraNodeFCP(FCPPluginConnectionTracker, Executor, 
PluginManager, String,
+     *      ClientSideFCPMessageHandler)
      *          The public interface to this constructor.
      */
-    private FCPPluginConnectionImpl(Executor executor, String serverPluginName,
-            ServerSideFCPMessageHandler server, ClientSideFCPMessageHandler 
client) {
+    private FCPPluginConnectionImpl(FCPPluginConnectionTracker tracker, 
Executor executor,
+            String serverPluginName, ServerSideFCPMessageHandler server,
+            ClientSideFCPMessageHandler client) {

+        assert(tracker != null);
         assert(executor != null);
         assert(serverPluginName != null);
         assert(server != null);
@@ -348,6 +371,10 @@
         this.server = new WeakReference<ServerSideFCPMessageHandler>(server);
         this.client = client;
         this.clientConnection = null;
+        this.defaultSendDirectionAdapters.put(SendDirection.ToServer,
+                new SendToServerAdapter(this));
+        this.defaultSendDirectionAdapters.put(SendDirection.ToClient,
+                new SendToClientAdapter(tracker, id));
     }

     /**
@@ -359,13 +386,11 @@
      * The client message handler is available as the passed {@link 
ClientSideFCPMessageHandler}
      * client.<br>
      * 
-     * <p>You <b>must</b> register any newly created connections at
-     * {@link 
FCPPluginConnectionTracker#registerConnection(FCPPluginConnection)} before 
handing
-     * them out to plugin code.</p>
+     * The returned connection is registered at the given {@link 
FCPPluginConnectionTracker}.
      */
-    static FCPPluginConnectionImpl constructForIntraNodeFCP(Executor executor,
-            PluginManager serverPluginManager, String serverPluginName,
-            ClientSideFCPMessageHandler client)
+    static FCPPluginConnectionImpl 
constructForIntraNodeFCP(FCPPluginConnectionTracker tracker,
+            Executor executor, PluginManager serverPluginManager,
+            String serverPluginName, ClientSideFCPMessageHandler client)
                 throws PluginNotFoundException {

         assert(executor != null);
@@ -373,8 +398,10 @@
         assert(serverPluginName != null);
         assert(client != null);

-        return new FCPPluginConnectionImpl(executor,
+        FCPPluginConnectionImpl result = new FCPPluginConnectionImpl(tracker, 
executor,
             serverPluginName, 
serverPluginManager.getPluginFCPServer(serverPluginName), client);
+        tracker.registerConnection(result);
+        return result;
     }

     /**
diff -r 1e611fd6dbf2 -r 9bc0180a4097 src/freenet/clients/fcp/FCPServer.java
--- a/src/freenet/clients/fcp/FCPServer.java    Mon Jan 19 17:27:18 2015 +0100
+++ b/src/freenet/clients/fcp/FCPServer.java    Mon Jan 19 17:46:15 2015 +0100
@@ -498,8 +498,10 @@
             throws PluginNotFoundException {

         FCPPluginConnectionImpl connection = 
FCPPluginConnectionImpl.constructForNetworkedFCP(
-            node.executor, node.pluginManager, serverPluginName, 
messageHandler);
-        pluginConnectionTracker.registerConnection(connection);
+            pluginConnectionTracker, node.executor, node.pluginManager,
+            serverPluginName, messageHandler);
+        // The constructor function already did this for us
+        /* pluginConnectionTracker.registerConnection(connection); */
         return connection;
     }

@@ -531,8 +533,10 @@
                 throws PluginNotFoundException {

         FCPPluginConnectionImpl connection = 
FCPPluginConnectionImpl.constructForIntraNodeFCP(
-            node.executor, node.pluginManager, serverPluginName, 
messageHandler);
-        pluginConnectionTracker.registerConnection(connection);
+            pluginConnectionTracker, node.executor, node.pluginManager,
+            serverPluginName, messageHandler);
+        // The constructor function already did this for us
+        /* pluginConnectionTracker.registerConnection(connection); */
         return connection;
     }

# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1421688234 -3600
#      Mon Jan 19 18:23:54 2015 +0100
# Node ID 6be89d28497a9dae74feb8db5c29cccdc5702b9d
# Parent  71d628581847701f24ac24287f394d9d228d15e6
FCPPluginConnectionImpl.constructForUnitTest(): Compile-fix

Sorry

diff -r 71d628581847 -r 6be89d28497a 
src/freenet/clients/fcp/FCPPluginConnectionImpl.java
--- a/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Mon Jan 19 
18:19:52 2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Mon Jan 19 
18:23:54 2015 +0100
@@ -430,7 +430,10 @@

         assert(server != null);
         assert(client != null);
-        return new FCPPluginConnectionImpl(new PooledExecutor(), 
server.toString(), server, client);
+        FCPPluginConnectionTracker tracker = new FCPPluginConnectionTracker();
+        tracker.start();
+        return new FCPPluginConnectionImpl(
+            tracker, new PooledExecutor(), server.toString(), server, client);
     }

     @Override
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1421688898 -3600
#      Mon Jan 19 18:34:58 2015 +0100
# Node ID af4895a54495e22146f8fa45d06d1bd385c1f7bd
# Parent  3c2ab5957f292e9dfe82e06e3fb08e742fcfe0da
FCPPluginConnectionImpl: Add getDefaultSendDirectionAdapter()

Uses the recently added table defaultSendDirectionAdapters to re-use
existing adapters.

diff -r 3c2ab5957f29 -r af4895a54495 
src/freenet/clients/fcp/FCPPluginConnectionImpl.java
--- a/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Mon Jan 19 
18:28:22 2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Mon Jan 19 
18:34:58 2015 +0100
@@ -1002,6 +1002,9 @@
         /** The {@link FCPPluginConnection#getID()} of the underlying 
connection. */
         private final UUID id;

+        /**
+         * Please use {@link 
FCPPluginConnectionImpl#getDefaultSendDirectionAdapter(SendDirection)}
+         * whenever possible to reuse adapters instead of creating new ones 
with this constructor.*/
         SendToClientAdapter(FCPPluginConnectionTracker tracker, UUID 
connectionID) {
             super(SendDirection.ToClient);
             this.tracker = tracker;
@@ -1036,6 +1039,9 @@

         private final FCPPluginConnection parent;

+        /**
+         * Please use {@link 
FCPPluginConnectionImpl#getDefaultSendDirectionAdapter(SendDirection)}
+         * whenever possible to reuse adapters instead of creating new ones 
with this constructor.*/
         SendToServerAdapter(FCPPluginConnectionImpl parent) {
             super(SendDirection.ToServer);
             this.parent = parent;
@@ -1050,6 +1056,17 @@
         }
     }

+    /**
+     * Returns a {@link DefaultSendDirectionAdapter} (which implements 
FCPPluginConnection) wrapped
+     * around this FCPPluginConnectionImpl for which the following send 
functions will then always
+     * send to the {@link SendDirection} which was passed to this function:<br>
+     * - {@link FCPPluginConnection#send(FCPPluginMessage)}<br>
+     * - {@link FCPPluginConnection#sendSynchronous(FCPPluginMessage, 
long)}<br><br>
+     */
+    public FCPPluginConnection getDefaultSendDirectionAdapter(SendDirection 
direction) {
+        return defaultSendDirectionAdapters.get(direction);
+    }
+
     @Override
     public String toString() {
         return "FCPPluginConnectionImpl (ID: " + id + "; server class: " + 
serverPluginName
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1421689122 -3600
#      Mon Jan 19 18:38:42 2015 +0100
# Node ID bb09b50c03529e15e635c865d701236b8782bd69
# Parent  af4895a54495e22146f8fa45d06d1bd385c1f7bd
FCPPluginConnectionImpl: Implement send functions without SendDirection

The following commits will fix the code which hands out
FCPPluginConnectionImpl to always wrap it inside a
DefaultSendDirectionAdapter like the JavaDoc already promises.

diff -r af4895a54495 -r bb09b50c0352 
src/freenet/clients/fcp/FCPPluginConnectionImpl.java
--- a/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Mon Jan 19 
18:34:58 2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Mon Jan 19 
18:38:42 2015 +0100
@@ -1067,6 +1067,44 @@
         return defaultSendDirectionAdapters.get(direction);
     }

+
+    /** 
+     * @throws NoSendDirectionSpecifiedException
+     *     Is always thrown since this function is only implemented for 
FCPPluginConnectionImpl
+     *     objects which are wrapped inside a {@link 
DefaultSendDirectionAdapter}.<br>
+     *     Objects of type FCPPluginConnectionImpl will never be handed out 
directly to the server
+     *     or client application code, they will always be wrapped in such an 
adapter - so this
+     *     function will work for servers and clients. */
+    @Override public void send(FCPPluginMessage message) {
+        throw new NoSendDirectionSpecifiedException();
+    }
+
+    /** 
+     * @throws NoSendDirectionSpecifiedException
+     *     Is always thrown since this function is only implemented for 
FCPPluginConnectionImpl
+     *     objects which are wrapped inside a {@link 
DefaultSendDirectionAdapter}.<br>
+     *     Objects of type FCPPluginConnectionImpl will never be handed out 
directly to the server
+     *     or client application code, they will always be wrapped in such an 
adapter - so this
+     *     function will work for servers and clients. */
+    @Override public FCPPluginMessage sendSynchronous(FCPPluginMessage message,
+            long timeoutNanoSeconds) {
+        throw new NoSendDirectionSpecifiedException();
+    }
+
+    /**
+     * @see FCPPluginConnectionImpl#send(FCPPluginMessage)
+     * @see FCPPluginConnectionImpl#sendSynchronous(FCPPluginMessage, long) */
+    @SuppressWarnings("serial")
+    private static final class NoSendDirectionSpecifiedException
+            extends UnsupportedOperationException {
+
+        public NoSendDirectionSpecifiedException() {
+            super("You must obtain a FCPPluginConnectionImpl with a default 
SendDirection via "
+                + "getDefaultSendDirectionAdapter() before you may use this 
function!");
+        }
+    }
+
+
     @Override
     public String toString() {
         return "FCPPluginConnectionImpl (ID: " + id + "; server class: " + 
serverPluginName
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1421689274 -3600
#      Mon Jan 19 18:41:14 2015 +0100
# Node ID 6a2f8daf88b27b6c6a9bc0f5e7c208a6d81f17b2
# Parent  bb09b50c03529e15e635c865d701236b8782bd69
FCPPluginConnectionImpl: Pass DefaultSendDirectionAdapter

... to message handlers of client / server.
What remains to be done is to adapt
PluginRespirator.connectToOtherPlugin() / getPluginConnectionByID() to
pass an adapter as well.

diff -r bb09b50c0352 -r 6a2f8daf88b2 
src/freenet/clients/fcp/FCPPluginConnectionImpl.java
--- a/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Mon Jan 19 
18:38:42 2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Mon Jan 19 
18:41:14 2015 +0100
@@ -697,7 +697,7 @@
                 try {
                     try {
                         reply = messageHandler.handlePluginFCPMessage(
-                            FCPPluginConnectionImpl.this, message);
+                            
getDefaultSendDirectionAdapter(direction.invert()), message);
                     } catch(Error e) {
                         // TODO: Code quality: This is a workaround for Java 6 
not having
                         // "catch(RuntimeException | Error e)". Once we are on 
Java 7, remove this
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1421695347 -3600
#      Mon Jan 19 20:22:27 2015 +0100
# Node ID 9947f6d4f1790f9cc7ec447700f935c142fd7d92
# Parent  6a2f8daf88b27b6c6a9bc0f5e7c208a6d81f17b2
FCPPluginConnectionTracker: Add getConnectionWeakReference()

Will be used for improving the implementation of
FCPPluginConnectionImpl.SendToClientAdapter

diff -r 6a2f8daf88b2 -r 9947f6d4f179 
src/freenet/clients/fcp/FCPPluginConnectionTracker.java
--- a/src/freenet/clients/fcp/FCPPluginConnectionTracker.java   Mon Jan 19 
18:41:14 2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginConnectionTracker.java   Mon Jan 19 
20:22:27 2015 +0100
@@ -80,7 +80,7 @@
      * from the {@link TreeMap}. For fast removal, we need their key in the 
map, which is the
      * connection ID, so we should store it in the {@link WeakReference}.
      */
-    private static final class ConnectionWeakReference
+    static final class ConnectionWeakReference
             extends WeakReference<FCPPluginConnection> {

         public final UUID connectionID;
@@ -136,23 +136,37 @@
      *     If there has been no connection with the given ID or if the client 
has disconnected.
      */
     public FCPPluginConnection getConnection(UUID connectionID) throws 
IOException {
-        ConnectionWeakReference ref = null;
+        ConnectionWeakReference ref = getConnectionWeakReference(connectionID);
+
+        FCPPluginConnection connection = ref.get();
+        
+        if(connection == null) {
+            throw new IOException("Client has closed the connection. "
+                                + "Connection ID = " + connectionID);
+        }
+        
+        return connection;
+    }
+    
+    /**
+     * Same as {@link #getConnection(UUID)} with the only difference of 
returning a
+     * {@link WeakReference} to the connection instead of the connection 
itself.<br>
+     * <b>Please do read its JavaDoc to understand when to use this!</b>
+     */
+    ConnectionWeakReference getConnectionWeakReference(UUID connectionID)
+            throws IOException {

         connectionsByIDLock.readLock().lock();
         try {
-            ref = connectionsByID.get(connectionID);
+            ConnectionWeakReference ref = connectionsByID.get(connectionID);
+            if(ref != null)
+                return ref;
         } finally {
             connectionsByIDLock.readLock().unlock();
         }

-        FCPPluginConnection connection = ref != null ? ref.get() : null;
-        
-        if(connection == null) {
-            throw new IOException("FCPPluginConnection not found, maybe client 
has disconnected."
-                + " Connection ID: " + connectionID);
-        }
-        
-        return connection;
+        throw new IOException("FCPPluginConnection not found, maybe client has 
disconnected."
+                            + " Connection ID: " + connectionID);
     }


# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1421696241 -3600
#      Mon Jan 19 20:37:21 2015 +0100
# Node ID 985e34cc79b19b4412e8e3d3606cffeec5d4751b
# Parent  9947f6d4f1790f9cc7ec447700f935c142fd7d92
FCPPluginConnectionImpl.SendToClientAdapter: Optimize

Store a WeakReference instead of always querying the connection from the
FCPPluginConnectionTracker. This will save us a O(N*LOG(N)) query from
the FCPPluginConnectionTracker TreeMap for each call of getConnection(),
and thus for each send() / sendSynchronous().

This means that the class' visibility can be trimmed to private since it
shall only be newly constructed from the FCPPluginConnectionImpl now,
otherwise the constructor is not guaranteed to work.
This also means that object identity of a FCPPluginConnection is
guaranteed: We will always use the same SendToClientAdapter stored in
the FCPluginConnectionImpl, because it only allows the outside to query
that one, not create fresh ones.

diff -r 9947f6d4f179 -r 985e34cc79b1 
src/freenet/clients/fcp/FCPPluginConnectionImpl.java
--- a/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Mon Jan 19 
20:22:27 2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Mon Jan 19 
20:37:21 2015 +0100
@@ -991,32 +991,48 @@
      * See section "Disconnecting properly" at {@link 
PluginRespirator#connectToOtherPlugin(
      * String, ClientSideFCPMessageHandler)}.
      */
-    static final class SendToClientAdapter extends DefaultSendDirectionAdapter 
{
+    private static final class SendToClientAdapter extends 
DefaultSendDirectionAdapter {

-        /** Is used to query the underlying FCPPluginConnectionImpl 
dynamically by its {@link UUID}
-         *  {@link #id} since this class, being aimed at being used by the 
server, may not keep a
-         *  strong reference to the connection to ensure that the client owns 
the power of purging
-         *  all strong references to it to cause disconnection. */
-        private final FCPPluginConnectionTracker tracker;
-        
-        /** The {@link FCPPluginConnection#getID()} of the underlying 
connection. */
-        private final UUID id;
+        /**
+         * {@link WeakReference} to the underlying FCPPluginConnectionImpl.<br>
+         * Once this becomes null, the connection is definitely dead - see
+         * {@link FCPPluginConnectionTracker}.<br>
+         * Notice: The ConnectionWeakReference child class of {@link 
WeakReference} is used because
+         * it also stores the connection ID, which is needed for {@link 
#getID()}.
+         */
+        private final FCPPluginConnectionTracker.ConnectionWeakReference 
connectionRef;

         /**
          * Please use {@link 
FCPPluginConnectionImpl#getDefaultSendDirectionAdapter(SendDirection)}
          * whenever possible to reuse adapters instead of creating new ones 
with this constructor.*/
         SendToClientAdapter(FCPPluginConnectionTracker tracker, UUID 
connectionID) {
             super(SendDirection.ToClient);
-            this.tracker = tracker;
-            this.id = connectionID;
+
+            // Reuse the WeakReference from the FCPPluginConnectionTracker 
instead of creating our
+            // own one since it has to keep a WeakReference for every 
connection anyway, and
+            // WeakReferences might be expensive to maintain for the VM.
+            try {
+                this.connectionRef = 
tracker.getConnectionWeakReference(connectionID);
+            } catch (IOException e) {
+                // This function should only be used during construction of 
the underlying
+                // FCPPluginConnectionImpl. While it is being constructed, it 
should not be
+                // considered as disconnected already, and thus the 
FCPPluginConnectionTracker
+                // should never throw IOException.
+                throw new RuntimeException("SHOULD NOT HAPPEN: " + e);
+            }
         }

         @Override protected FCPPluginConnection getConnection() throws 
IOException {
-            return tracker.getConnection(id);
+            FCPPluginConnection connection = connectionRef.get();
+            if(connection == null) {
+                throw new IOException("Client has closed the connection. "
+                                    + "Connection ID = " + 
connectionRef.connectionID);
+            }
+            return connection;
         }

         @Override public UUID getID() {
-            return id;
+            return connectionRef.connectionID;
         }
     }

# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1421697102 -3600
#      Mon Jan 19 20:51:42 2015 +0100
# Node ID 7fcaf96a4528b46e999f4881f6e07e4cc78f1c0f
# Parent  985e34cc79b19b4412e8e3d3606cffeec5d4751b
FCPPluginConnectionTracker: Store FCPPluginConnection*Impl*

instead of just FCPPluginConnection.
This is necessary because new code in FCPServer soon to be committed
will need functions of the Impl which do not make sense to add to the
parent interface.

diff -r 985e34cc79b1 -r 7fcaf96a4528 
src/freenet/clients/fcp/FCPPluginConnectionTracker.java
--- a/src/freenet/clients/fcp/FCPPluginConnectionTracker.java   Mon Jan 19 
20:37:21 2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginConnectionTracker.java   Mon Jan 19 
20:51:42 2015 +0100
@@ -17,8 +17,9 @@
 import freenet.support.io.NativeThread;

 /**
- * <p>Keeps a list of all {@link FCPPluginConnection}s which are connected to 
server plugins running
- * in the node. Allows the server plugins to query a client connection by its 
{@link UUID}.</p>
+ * Keeps a list of all {@link FCPPluginConnectionImpl}s which are connected to 
server plugins
+ * running in the node. Allows the server plugins to query a client connection 
by its {@link UUID}.
+ * <br><br>
  * 
  * <p>To understand the purpose of this, please consider the following:<br/>
  * The normal flow of plugin FCP is that clients send messages to a server 
plugin, and the server
@@ -69,8 +70,8 @@
      * Queue which monitors nulled weak references in {@link 
#connectionsByID}.<br>
      * Monitored in {@link #realRun()}.
      */
-    private final ReferenceQueue<FCPPluginConnection> closedConnectionsQueue
-        = new ReferenceQueue<FCPPluginConnection>();
+    private final ReferenceQueue<FCPPluginConnectionImpl> 
closedConnectionsQueue
+        = new ReferenceQueue<FCPPluginConnectionImpl>();


     /**
@@ -81,12 +82,12 @@
      * connection ID, so we should store it in the {@link WeakReference}.
      */
     static final class ConnectionWeakReference
-            extends WeakReference<FCPPluginConnection> {
+            extends WeakReference<FCPPluginConnectionImpl> {

         public final UUID connectionID;

-        public ConnectionWeakReference(FCPPluginConnection referent,
-                ReferenceQueue<FCPPluginConnection> referenceQueue) {
+        public ConnectionWeakReference(FCPPluginConnectionImpl referent,
+                ReferenceQueue<FCPPluginConnectionImpl> referenceQueue) {

             super(referent, referenceQueue);
             connectionID = referent.getID();
@@ -94,16 +95,16 @@
     }

     /**
-     * Stores the {@link FCPPluginConnection} so in the future it can be 
obtained by its ID with
+     * Stores the {@link FCPPluginConnectionImpl} so in the future it can be 
obtained by its ID with
      * {@link #getConnection(UUID)}.
      * 
-     * <b>Must</b> be called for any newly created {@link FCPPluginConnection} 
before passing it to
-     * {@link 
ServerSideFCPMessageHandler#handlePluginFCPMessage(FCPPluginConnection,
+     * <b>Must</b> be called for any newly created {@link 
FCPPluginConnectionImpl} before passing it
+     * to {@link 
ServerSideFCPMessageHandler#handlePluginFCPMessage(FCPPluginConnection,
      * FCPPluginMessage)}.
      * 
      * Unregistration is not supported and not necessary.
      */
-   void registerConnection(FCPPluginConnection connection) {
+   void registerConnection(FCPPluginConnectionImpl connection) {
         connectionsByIDLock.writeLock().lock();
         try {
             // No duplicate checks needed: FCPPluginConnection.getID() is a 
random UUID.
@@ -135,10 +136,10 @@
      * @throws IOException
      *     If there has been no connection with the given ID or if the client 
has disconnected.
      */
-    public FCPPluginConnection getConnection(UUID connectionID) throws 
IOException {
+    public FCPPluginConnectionImpl getConnection(UUID connectionID) throws 
IOException {
         ConnectionWeakReference ref = getConnectionWeakReference(connectionID);

-        FCPPluginConnection connection = ref.get();
+        FCPPluginConnectionImpl connection = ref.get();

         if(connection == null) {
             throw new IOException("Client has closed the connection. "
diff -r 985e34cc79b1 -r 7fcaf96a4528 src/freenet/clients/fcp/FCPServer.java
--- a/src/freenet/clients/fcp/FCPServer.java    Mon Jan 19 20:37:21 2015 +0100
+++ b/src/freenet/clients/fcp/FCPServer.java    Mon Jan 19 20:51:42 2015 +0100
@@ -71,8 +71,8 @@
        String bindTo;
        private String allowedHosts;
        AllowedHosts allowedHostsFullAccess;
-    /** Stores {@link FCPPluginConnection} objects by ID and automatically 
garbage collects them so
-     *  we don't have to bloat this class with that. */
+    /** Stores {@link FCPPluginConnectionImpl} objects by ID and automatically 
garbage collects them
+     *  so we don't have to bloat this class with that. */
        final FCPPluginConnectionTracker pluginConnectionTracker;
        final WeakHashMap<String, PersistentRequestClient> rebootClientsByName;
        final PersistentRequestClient globalRebootClient;
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1421697521 -3600
#      Mon Jan 19 20:58:41 2015 +0100
# Node ID 26f3fc23479755d7b9d3da6b27d566fff5e6754d
# Parent  7fcaf96a4528b46e999f4881f6e07e4cc78f1c0f
FCPServer: Set default send direction in returned FCPPluginConnections

.. by using the recently implemented getDefaultSendDirectionAdapter().

diff -r 7fcaf96a4528 -r 26f3fc234797 src/freenet/clients/fcp/FCPServer.java
--- a/src/freenet/clients/fcp/FCPServer.java    Mon Jan 19 20:51:42 2015 +0100
+++ b/src/freenet/clients/fcp/FCPServer.java    Mon Jan 19 20:58:41 2015 +0100
@@ -27,6 +27,7 @@
 import freenet.client.async.PersistentJob;
 import freenet.clients.fcp.ClientGet.ReturnType;
 import freenet.clients.fcp.ClientRequest.Persistence;
+import freenet.clients.fcp.FCPPluginConnection.SendDirection;
 import freenet.config.Config;
 import freenet.config.InvalidConfigValueException;
 import freenet.config.SubConfig;
@@ -524,6 +525,10 @@
      * {@link PluginRespirator#connectToOtherPlugin(String,
      * FredPluginFCPMessageHandler.ClientSideFCPMessageHandler)}. Plugins must 
use that instead.</p>
      * 
+     * ATTENTION: Since this function is only to be used by the aforementioned 
connectToPlugin()
+     * which in turn is only to be used by clients, the returned connection 
will have a default send
+     * direction of {@link SendDirection#ToServer}.
+     * 
      * @see FCPPluginConnectionImpl
      *     The class JavaDoc of FCPPluginConnectionImpl explains the code path 
for both networked
      *     and non-networked FCP.
@@ -537,18 +542,27 @@
             serverPluginName, messageHandler);
         // The constructor function already did this for us
         /* pluginConnectionTracker.registerConnection(connection); */
-        return connection;
+        return 
connection.getDefaultSendDirectionAdapter(SendDirection.ToServer);
     }

     /**
      * <p><b>The documentation of {@link 
FCPPluginConnectionTracker#getConnection(UUID)} applies to
      * this function.</b></p>
      * 
+     * ATTENTION: Only for internal use by the frontend function
+     * {@link PluginRespirator#getPluginConnectionByID(UUID)}. Plugins must 
use that instead.<br>
+     * <br>
+     * 
+     * ATTENTION: Since this function is only to be used by the aforementioned
+     * getPluginConnectionByID() which in turn is only to be used by servers, 
the returned
+     * connection will have a default send direction of {@link 
SendDirection#ToClient}.
+     * 
      * @see FCPPluginConnectionTracker
      *     The JavaDoc of FCPPluginConnectionTracker explains the general 
purpose of this mechanism.
      */
     public final FCPPluginConnection getPluginConnectionByID(UUID 
connectionID) throws IOException {
-        return pluginConnectionTracker.getConnection(connectionID);
+        return pluginConnectionTracker.getConnection(connectionID)
+                                      
.getDefaultSendDirectionAdapter(SendDirection.ToClient);
     }

        public PersistentRequestClient registerRebootClient(String name, 
NodeClientCore core, FCPConnectionHandler handler) {
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1421697610 -3600
#      Mon Jan 19 21:00:10 2015 +0100
# Node ID 6661a193d6dc6af1517a57f153b82c7b01de9817
# Parent  26f3fc23479755d7b9d3da6b27d566fff5e6754d
FCPServer.createFCPPluginConnectionForIntraNodeFCP(): Trim return type

Reducing this to the parent interface FCPPluginConnection will allow
setting the visibility of FCPPluginConnectionImpl to package private
since what this commit changes is IIRC the only place which uses
FCPPluginConnectionImpl in a non-package-private way.

- This was made possible by implementing the usage of
getDefaultSendDirectionAdapter() in this function. I had speculated that
this function would be called in a caller of the FCPServer
function different package, which is why this used to return the
*Impl. But now that we call it here already, the FCPServer doesn't need
to return the Impl.

diff -r 26f3fc234797 -r 6661a193d6dc src/freenet/clients/fcp/FCPServer.java
--- a/src/freenet/clients/fcp/FCPServer.java    Mon Jan 19 20:58:41 2015 +0100
+++ b/src/freenet/clients/fcp/FCPServer.java    Mon Jan 19 21:00:10 2015 +0100
@@ -533,7 +533,7 @@
      *     The class JavaDoc of FCPPluginConnectionImpl explains the code path 
for both networked
      *     and non-networked FCP.
      */
-    public final FCPPluginConnectionImpl 
createFCPPluginConnectionForIntraNodeFCP(
+    public final FCPPluginConnection createFCPPluginConnectionForIntraNodeFCP(
             String serverPluginName, ClientSideFCPMessageHandler 
messageHandler)
                 throws PluginNotFoundException {

# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1421698282 -3600
#      Mon Jan 19 21:11:22 2015 +0100
# Node ID 78bee089eb2fa9eaaa3a24512cc10b62f05a243c
# Parent  a314c83833894c988e0c9a546d6b5ffb6c21fc63
FCPPluginConnectionImpl: Trim visibility

diff -r a314c8383389 -r 78bee089eb2f 
src/freenet/clients/fcp/FCPPluginConnectionImpl.java
--- a/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Mon Jan 19 
21:09:39 2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Mon Jan 19 
21:11:22 2015 +0100
@@ -104,7 +104,7 @@
  *   <br/>This mechanism also works for networked FCP.<br>
  * </p></p>
  */
-public final class FCPPluginConnectionImpl implements FCPPluginConnection {
+final class FCPPluginConnectionImpl implements FCPPluginConnection {

     /** Automatically set to true by {@link Logger} if the log level is set to
      *  {@link LogLevel#DEBUG} for this class.
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1421701166 -3600
#      Mon Jan 19 21:59:26 2015 +0100
# Node ID 91d2b74586bb4bd973f62e51e4082fd674c57d6a
# Parent  c426dc857d67ac35539bd19b93079fd6127c599a
FCPPluginConnectionImpl: Fix "SHOULD NOT HAPPEN: java.io.IOException:"

Unit test failure would be as follows:

[junit] SHOULD NOT HAPPEN: java.io.IOException: FCPPluginConnection not
found, maybe client has disconnected. Connection ID:
83665b37-32a6-41f3-9af7-5ca20db13324
[junit] java.lang.RuntimeException: SHOULD NOT HAPPEN:
java.io.IOException: FCPPluginConnection not found, maybe client has
disconnected. Connection ID: 83665b37-32a6-41f3-9af7-5ca20db13324
[junit]     at
freenet.clients.fcp.FCPPluginConnectionImpl$SendToClientAdapter.<init>(FCPPluginConnectionImpl.java:1021)
[junit]     at
freenet.clients.fcp.FCPPluginConnectionImpl.<init>(FCPPluginConnectionImpl.java:376)
[junit]     at
freenet.clients.fcp.FCPPluginConnectionImpl.constructForUnitTest(FCPPluginConnectionImpl.java:435)
[junit]     at
freenet.clients.fcp.FCPPluginConnectionImplTest.testSendSynchronousThreadSafety(FCPPluginConnectionImplTest.java:38)

diff -r c426dc857d67 -r 91d2b74586bb 
src/freenet/clients/fcp/FCPPluginConnectionImpl.java
--- a/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Mon Jan 19 
21:11:52 2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Mon Jan 19 
21:59:26 2015 +0100
@@ -311,6 +311,9 @@
         this.clientConnection = clientConnection;
         this.defaultSendDirectionAdapters.put(SendDirection.ToServer,
                 new SendToServerAdapter(this));
+        // new SendToClientAdapter() will need to query this connection from 
the tracker already.
+        // Thus, we have to register before constructing it.
+        tracker.registerConnection(this);
         this.defaultSendDirectionAdapters.put(SendDirection.ToClient,
                 new SendToClientAdapter(tracker, id));
     }
@@ -335,11 +338,8 @@
         assert(serverPluginName != null);
         assert(clientConnection != null);

-        FCPPluginConnectionImpl result = new FCPPluginConnectionImpl(tracker, 
executor,
-            serverPluginName, 
serverPluginManager.getPluginFCPServer(serverPluginName),
-            clientConnection);
-        tracker.registerConnection(result);
-        return result;
+        return new FCPPluginConnectionImpl(tracker, executor, serverPluginName,
+            serverPluginManager.getPluginFCPServer(serverPluginName), 
clientConnection);
     }


@@ -373,6 +373,9 @@
         this.clientConnection = null;
         this.defaultSendDirectionAdapters.put(SendDirection.ToServer,
                 new SendToServerAdapter(this));
+        // new SendToClientAdapter() will need to query this connection from 
the tracker already.
+        // Thus, we have to register before constructing it.
+        tracker.registerConnection(this);
         this.defaultSendDirectionAdapters.put(SendDirection.ToClient,
                 new SendToClientAdapter(tracker, id));
     }
@@ -398,10 +401,8 @@
         assert(serverPluginName != null);
         assert(client != null);

-        FCPPluginConnectionImpl result = new FCPPluginConnectionImpl(tracker, 
executor,
-            serverPluginName, 
serverPluginManager.getPluginFCPServer(serverPluginName), client);
-        tracker.registerConnection(result);
-        return result;
+        return new FCPPluginConnectionImpl(tracker, executor, serverPluginName,
+            serverPluginManager.getPluginFCPServer(serverPluginName), client);
     }

     /**
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1421773177 -3600
#      Tue Jan 20 17:59:37 2015 +0100
# Node ID 975557185f03b534046300d7688933ce8ce596c8
# Parent  3076f7d2292da011dbdbed5328cc9a65d5cad395
ServerSideFCPMessageHandler: Allow keeping strong refs to connections

The FCPPluginConnections which we pass to the message handler have
recently been changed to be a
FCPPluginConnectionImpl.SendToClientAdapter, which
internally only keeps a WeakReference to the FCPPluginConnectionImpl.
Thus, the server may keep a strong reference to that wrapper
without preventing GC of the actual FCPPluginConnectionImpl.

Additional included JavaDoc improvements:
- The "Notice that there is no..." sentence of the last item in the
enumeration is moved to the front to structure the sentences to be
ordered as 1. what is wrong 2. how to deal with it
- Don't push people very much to implement "Ping": Say "you may" instead
of "you are encouraged to". It is also possible to have implicit pinging
for stuff which sends messages very frequently anyway.

diff -r 3076f7d2292d -r 975557185f03 
src/freenet/pluginmanager/FredPluginFCPMessageHandler.java
--- a/src/freenet/pluginmanager/FredPluginFCPMessageHandler.java        Tue Jan 
20 17:22:00 2015 +0100
+++ b/src/freenet/pluginmanager/FredPluginFCPMessageHandler.java        Tue Jan 
20 17:59:37 2015 +0100
@@ -106,10 +106,7 @@
         /**
          * <p>Is called to handle messages from your clients.<br/>
          * <b>Must not</b> block for very long and thus must only do small 
amounts of processing.
-         * <br/>
-         * You <b>must not</b> keep a hard reference to the passed {@link 
FCPPluginConnection}
-         * object outside of the scope of this function: This would prevent 
client plugins from
-         * being unloaded. See below for how to keep a reference to a client 
connection.</p>
+         * </p>
          * 
          * <p>If you ...<br/>
          * - Need a long time to compute a reply.<br/>
@@ -117,31 +114,28 @@
          *   the client after having exited this function; maybe even 
triggered by events at your
          *   plugin, not by client messages.<br/>
          * Then you should:<br/>
-         * - Obtain the {@link UUID} of the client connection via {@link 
FCPPluginConnection#
-         *   getID()}, store the {@link UUID}, and exit this message handling 
function.<br/>
+         * - Store the passed {@link FCPPluginConnection}. If you cannot store 
objects in memory,
+         *   for example because you are using a database, you can get the 
{@link UUID} of the
+         *   connection via {@link FCPPluginConnection#getID()}, store only 
that, and then in the
+         *   future get back the connection using
+         *   {@link PluginRespirator#getPluginConnectionByID(UUID)}.<br>
          * - Compute your reply in another thread.</br>
-         * - Once you're ready to send the reply, use
-         *   {@link PluginRespirator#getPluginConnectionByID(UUID)} to obtain 
the original
-         *   {@link FCPPluginConnection}, and then send the message using the 
send functions of the
+         * - Once you're ready to send the reply, send the message using the 
send functions of the
          *   {@link FCPPluginConnection}.<br/>
-         * - If you keep client connection {@link UUID} for longer than 
sending a single reply, make
-         *   sure to prevent excessive growth of your connection database upon 
client disconnection
+         * - Notice that there is no explicit disconnection mechanism. Clients 
can come and go as
+         *   they please. The only way to be sure that a connection is alive 
is by checking whether
+         *   the client replies to messages.<br>
+         *   Thus, if you store client connections for longer than sending a 
single reply, make sure
+         *   to prevent excessive growth of your connection database upon 
client disconnection
          *   by implementing a garbage collection mechanism as follows:<br>
          *   Periodically send a message at each connection and check if you 
get a reply within a
          *   reasonable timeout to check whether the connection is still 
alive. Drop the connection
-         *   if not.<br>
-         *   Notice that there is no explicit disconnection mechanism. Clients 
can come and go as
-         *   they please. The only way to be sure that a connection is alive 
is by checking whether
-         *   the client replies to messages. You are encouraged to make a 
"Ping" message with a
-         *   "Pong" response a requirement for your server's protocol.<br>
+         *   if not. You may make a "Ping" message with a "Pong" response a 
requirement for your
+         *   server's protocol.<br>
          * </p>
          * 
          * @param connection
          *            The connection of the client which sent the 
message.<br/><br/>
-         *            You <b>must not</b> keep a hard reference to this object 
outside of the scope
-         *            of this function: This would prevent client plugins from 
being unloaded. See
-         *            the head of the documentation of this function for an 
explanation of how to
-         *            store a pointer to a certain client connection.<br/><br/>
          * 
          *            You <b>must not</b> use its send functions for sending 
back the main reply.
          *            Instead, use the return value for shipping the reply. 
(You are free to send
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1421774244 -3600
#      Tue Jan 20 18:17:24 2015 +0100
# Node ID 37ef59f5f65f86cbcfc3894ee3aa5f6d5142a40a
# Parent  975557185f03b534046300d7688933ce8ce596c8
FCPPluginConnectionImpl: Detect bogus reply message identifiers

The FredPluginFCPMessageHandler instructs users to always construct
reply messages in a way mich makes them have the same identifier as the
original messagge. Thus, we shouldn't allow reply messages which have a
differing identifier.

diff -r 975557185f03 -r 37ef59f5f65f 
src/freenet/clients/fcp/FCPPluginConnectionImpl.java
--- a/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Tue Jan 20 
17:59:37 2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Tue Jan 20 
18:17:24 2015 +0100
@@ -787,6 +787,18 @@

                         reply = null;
                     }
+
+                    if(!reply.identifier.equals(message.identifier)) {
+                        Logger.error(messageHandler, 
"FredPluginFCPMessageHandler tried to send a"
+                            + " reply with with different identifier than 
original message."
+                            + " See JavaDoc of its member interfaces for how 
to do this properly."
+                            + " connection = " + FCPPluginConnectionImpl.this
+                            + "; original message SendDirection = " + direction
+                            + "; original message = " + message
+                            + "; reply = " + reply);
+
+                        reply = null;
+                    }
                 } else if(reply == null) {
                     if(!message.isReplyMessage()) {
                         // The message handler did not not ship a reply even 
though it would have
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1421774719 -3600
#      Tue Jan 20 18:25:19 2015 +0100
# Node ID b4d2452d8d13fdad4eb93f3b3bcbfc5830dd6537
# Parent  37ef59f5f65f86cbcfc3894ee3aa5f6d5142a40a
DefaultSendDirectionAdapter: Implement toString()

As it is specified in FCPPluginConnection to contain debug information
about the FCPPluginConnection, and FCPPluginConnectionImpl implements it
to provide much information.

diff -r 37ef59f5f65f -r b4d2452d8d13 
src/freenet/clients/fcp/FCPPluginConnectionImpl.java
--- a/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Tue Jan 20 
18:17:24 2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Tue Jan 20 
18:25:19 2015 +0100
@@ -1111,6 +1111,15 @@
         @Override public UUID getID() {
             return connectionRef.connectionID;
         }
+        
+        @Override public String toString() {
+            String prefix = "SendToClientAdapter for ";
+            try {
+                return prefix + getConnection();
+            } catch(IOException e) {
+                return prefix + " FCPPluginConnectionImpl (" + e.getMessage() 
+ ")";
+            }
+        }
     }

     /**
@@ -1147,6 +1156,10 @@
         @Override public UUID getID() {
             return parent.getID();
         }
+        
+        @Override public String toString() {
+            return "SendToServerAdapter for " + parent;
+        }
     }

     /**
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1421775531 -3600
#      Tue Jan 20 18:38:51 2015 +0100
# Node ID 810ec77790f2aca7f900019ef380bae5367dff5d
# Parent  b4d2452d8d13fdad4eb93f3b3bcbfc5830dd6537
FCPPluginConnectionImpl: Fix NullPointerException

diff -r b4d2452d8d13 -r 810ec77790f2 
src/freenet/clients/fcp/FCPPluginConnectionImpl.java
--- a/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Tue Jan 20 
18:25:19 2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Tue Jan 20 
18:38:51 2015 +0100
@@ -786,9 +786,7 @@
                             + "; reply = " + reply);

                         reply = null;
-                    }
-
-                    if(!reply.identifier.equals(message.identifier)) {
+                    } else if(!reply.identifier.equals(message.identifier)) {
                         Logger.error(messageHandler, 
"FredPluginFCPMessageHandler tried to send a"
                             + " reply with with different identifier than 
original message."
                             + " See JavaDoc of its member interfaces for how 
to do this properly."
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1421775646 -3600
#      Tue Jan 20 18:40:46 2015 +0100
# Node ID c44303d925deff911c63f0556ea89c33716c4cc3
# Parent  810ec77790f2aca7f900019ef380bae5367dff5d
FCPPluginConnectionImpl: Detect non-reply replies

The FredPluginFCPMessageHandler JavaDoc instructs users to always
construct reply messages in a way which causes them to be marked as
reply. Thus, we shouldn't allow reply messages which have
!isReplyMessage().

diff -r 810ec77790f2 -r c44303d925de 
src/freenet/clients/fcp/FCPPluginConnectionImpl.java
--- a/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Tue Jan 20 
18:38:51 2015 +0100
+++ b/src/freenet/clients/fcp/FCPPluginConnectionImpl.java      Tue Jan 20 
18:40:46 2015 +0100
@@ -786,6 +786,16 @@
                             + "; reply = " + reply);

                         reply = null;
+                    } else if(!reply.isReplyMessage()) {
+                        Logger.error(messageHandler, 
"FredPluginFCPMessageHandler tried to send a"
+                            + " non-reply message as reply. See JavaDoc of its 
member interfaces"
+                            + " for how to do this properly."
+                            + " connection = " + FCPPluginConnectionImpl.this
+                            + "; original message SendDirection = " + direction
+                            + "; original message = " + message
+                            + "; reply = " + reply);
+
+                        reply = null;
                     } else if(!reply.identifier.equals(message.identifier)) {
                         Logger.error(messageHandler, 
"FredPluginFCPMessageHandler tried to send a"
                             + " reply with with different identifier than 
original message."
# HG changeset patch
# User xor-freenet <xor at freenetproject.org>
# Date 1421784049 -3600
#      Tue Jan 20 21:00:49 2015 +0100
# Node ID 130f29438bccc10b6ebe0b07af407113b0e667b4
# Parent  c44303d925deff911c63f0556ea89c33716c4cc3
PluginRespirator.getPluginConnectionByID(): Linkify "connection"

diff -r c44303d925de -r 130f29438bcc 
src/freenet/pluginmanager/PluginRespirator.java
--- a/src/freenet/pluginmanager/PluginRespirator.java   Tue Jan 20 18:40:46 
2015 +0100
+++ b/src/freenet/pluginmanager/PluginRespirator.java   Tue Jan 20 21:00:49 
2015 +0100
@@ -179,7 +179,7 @@
     /**
      * Allows FCP server plugins, that is plugins which implement
      * {@link FredPluginFCPMessageHandler.ServerSideFCPMessageHandler}, to 
obtain an existing client
-     * connection by its {@link UUID} - if the client is still 
connected.<br><br>
+     * {@link FCPPluginConnection} by its {@link UUID} - if the client is 
still connected.<br><br>
      * 
      * <b>Must not</b> be used by client plugins: They shall instead keep a 
hard reference to the
      * {@link FCPPluginConnection} in memory after they have received it from


-- 
unpolitisch sein
heißt politisch sein, 
ohne es zu merken. 
- ArneBab ( http://draketo.de )
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: sync-fcp-diff-since-review-bertm-only-functional.diff
URL: 
<https://emu.freenetproject.org/pipermail/devl/attachments/20150220/7b7726c2/attachment-0001.ksh>

Reply via email to