Update Server, breaks API + remove deprecated
authorNiki Roo <niki@nikiroo.be>
Tue, 28 Nov 2017 08:35:32 +0000 (09:35 +0100)
committerNiki Roo <niki@nikiroo.be>
Tue, 28 Nov 2017 08:35:32 +0000 (09:35 +0100)
15 files changed:
changelog.md
src/be/nikiroo/utils/TraceHandler.java
src/be/nikiroo/utils/serial/server/ConnectAction.java [moved from src/be/nikiroo/utils/serial/ConnectAction.java with 95% similarity]
src/be/nikiroo/utils/serial/server/ConnectActionClient.java [moved from src/be/nikiroo/utils/serial/ConnectActionClient.java with 69% similarity]
src/be/nikiroo/utils/serial/server/ConnectActionClientObject.java [new file with mode: 0644]
src/be/nikiroo/utils/serial/server/ConnectActionClientString.java [new file with mode: 0644]
src/be/nikiroo/utils/serial/server/ConnectActionServer.java [moved from src/be/nikiroo/utils/serial/ConnectActionServer.java with 51% similarity]
src/be/nikiroo/utils/serial/server/ConnectActionServerObject.java [new file with mode: 0644]
src/be/nikiroo/utils/serial/server/ConnectActionServerString.java [new file with mode: 0644]
src/be/nikiroo/utils/serial/server/Server.java [moved from src/be/nikiroo/utils/serial/Server.java with 82% similarity]
src/be/nikiroo/utils/serial/server/ServerObject.java [new file with mode: 0644]
src/be/nikiroo/utils/serial/server/ServerString.java [new file with mode: 0644]
src/be/nikiroo/utils/test/SerialTest.java
src/be/nikiroo/utils/test/TestCase.java
src/be/nikiroo/utils/test/TestLauncher.java

index 34046e81b71f22fc25654675104b86cd596578fe..1df57c7ed66d3447bcd5c51ba9712f36d50f6f09 100644 (file)
@@ -1,10 +1,11 @@
 # nikiroo-utils
 
-## Version WIP
+## Version 3.0.0
 
 - jDoc
 - Fix bugs in Server (it was not possible to send objects back to client)
-- Improve code in Server (including tests)
+- Improve code in Server (including tests), breaks API
+- Remove some deprecated things
 
 ## Version 2.2.3
 
index 309e8af6d393f31823a4200e719ec051e1570ad3..6541a8bfd5b9add51643686a7f641f250b201809 100644 (file)
@@ -77,28 +77,4 @@ public class TraceHandler {
                        System.out.println(message);
                }
        }
-
-       // old stuff:
-
-       /**
-        * Use the parameters in the constructor instead.
-        * 
-        * @param showTraces
-        *            show the traces
-        */
-       @Deprecated
-       public void setShowTraces(boolean showTraces) {
-               this.showTraces = showTraces;
-       }
-
-       /**
-        * Use the parameters in the constructor instead.
-        * 
-        * @param showErrorDetails
-        *            show the details on errors
-        */
-       @Deprecated
-       public void setShowErrorDetails(boolean showErrorDetails) {
-               this.showErrorDetails = showErrorDetails;
-       }
 }
similarity index 95%
rename from src/be/nikiroo/utils/serial/ConnectAction.java
rename to src/be/nikiroo/utils/serial/server/ConnectAction.java
index dfc1a2bb422138ea8acbf930a831d0c6d7a7a0da..8f57c628fb18e861c9805174468f5ccb0ce0fba1 100644 (file)
@@ -1,4 +1,4 @@
-package be.nikiroo.utils.serial;
+package be.nikiroo.utils.serial.server;
 
 import java.io.BufferedReader;
 import java.io.IOException;
@@ -7,6 +7,8 @@ import java.io.OutputStreamWriter;
 import java.net.Socket;
 
 import be.nikiroo.utils.Version;
+import be.nikiroo.utils.serial.Exporter;
+import be.nikiroo.utils.serial.Importer;
 
 /**
  * Base class used for the client/server basic handling.
@@ -154,7 +156,7 @@ abstract class ConnectAction {
         * @throws ClassNotFoundException
         *             if a class described in the serialised data cannot be found
         */
-       protected Object send(Object data) throws IOException,
+       protected Object sendObject(Object data) throws IOException,
                        NoSuchFieldException, NoSuchMethodException, ClassNotFoundException {
                synchronized (lock) {
                        String rep = sendString(new Exporter().append(data).toString(true));
@@ -190,10 +192,10 @@ abstract class ConnectAction {
         * @throws java.lang.NullPointerException
         *             if the counter part has no data to send
         */
-       protected Object rec() throws IOException, NoSuchFieldException,
+       protected Object recObject() throws IOException, NoSuchFieldException,
                        NoSuchMethodException, ClassNotFoundException,
                        java.lang.NullPointerException {
-               String str = flushString();
+               String str = recString();
                if (str == null) {
                        throw new NullPointerException("No more data available");
                }
@@ -225,7 +227,7 @@ abstract class ConnectAction {
                        }
 
                        contentToSend = true;
-                       return flushString();
+                       return recString();
                }
        }
 
@@ -243,7 +245,7 @@ abstract class ConnectAction {
         * @throws IOException
         *             in case of I/O error
         */
-       protected String flushString() throws IOException {
+       protected String recString() throws IOException {
                synchronized (lock) {
                        if (server || contentToSend) {
                                if (contentToSend) {
similarity index 69%
rename from src/be/nikiroo/utils/serial/ConnectActionClient.java
rename to src/be/nikiroo/utils/serial/server/ConnectActionClient.java
index 83537025d00e103adc127ebad31b096129609f85..626b62f78494ab4fdb818220629a281bc3507f14 100644 (file)
@@ -1,4 +1,4 @@
-package be.nikiroo.utils.serial;
+package be.nikiroo.utils.serial.server;
 
 import java.io.IOException;
 import java.net.Socket;
@@ -13,8 +13,13 @@ import be.nikiroo.utils.Version;
  * 
  * @author niki
  */
-public class ConnectActionClient {
-       private ConnectAction action;
+abstract class ConnectActionClient {
+       /**
+        * The underlying {@link ConnectAction}.
+        * <p>
+        * Cannot be NULL.
+        */
+       protected ConnectAction action;
 
        /**
         * Create a new {@link ConnectActionClient} with the current application
@@ -127,31 +132,6 @@ public class ConnectActionClient {
        public void action(Version serverVersion) throws Exception {
        }
 
-       /**
-        * Serialise and send the given object to the server (and return the
-        * deserialised answer).
-        * 
-        * @param data
-        *            the data to send
-        * 
-        * @return the answer, which can be NULL
-        * 
-        * @throws IOException
-        *             in case of I/O error
-        * @throws NoSuchFieldException
-        *             if the serialised data contains information about a field
-        *             which does actually not exist in the class we know of
-        * @throws NoSuchMethodException
-        *             if a class described in the serialised data cannot be created
-        *             because it is not compatible with this code
-        * @throws ClassNotFoundException
-        *             if a class described in the serialised data cannot be found
-        */
-       public Object send(Object data) throws IOException, NoSuchFieldException,
-                       NoSuchMethodException, ClassNotFoundException {
-               return action.send(data);
-       }
-
        /**
         * Handler called when an unexpected error occurs in the code.
         * <p>
@@ -162,24 +142,4 @@ public class ConnectActionClient {
         */
        protected void onError(@SuppressWarnings("unused") Exception e) {
        }
-
-       // old stuff:
-
-       /**
-        * Do not use. Will never be called.
-        */
-       @SuppressWarnings({ "unused", "javadoc" })
-       @Deprecated
-       protected void onClientVersionReceived(Version clientVersion) {
-       }
-
-       /**
-        * Do not use, it is not supposed to be called from the outside.
-        */
-       @SuppressWarnings({ "unused", "javadoc" })
-       @Deprecated
-       public Object flush() throws NoSuchFieldException, NoSuchMethodException,
-                       ClassNotFoundException, IOException, java.lang.NullPointerException {
-               return null;
-       }
 }
\ No newline at end of file
diff --git a/src/be/nikiroo/utils/serial/server/ConnectActionClientObject.java b/src/be/nikiroo/utils/serial/server/ConnectActionClientObject.java
new file mode 100644 (file)
index 0000000..e9673ac
--- /dev/null
@@ -0,0 +1,105 @@
+package be.nikiroo.utils.serial.server;
+
+import java.io.IOException;
+import java.net.Socket;
+
+import be.nikiroo.utils.Version;
+
+/**
+ * Class used for the client basic handling.
+ * <p>
+ * It represents a single action: a client is expected to only execute one
+ * action.
+ * 
+ * @author niki
+ */
+public class ConnectActionClientObject extends ConnectActionClient {
+       /**
+        * Create a new {@link ConnectActionClientObject} with the current
+        * application version (see {@link Version#getCurrentVersion()}) as the
+        * client version.
+        * 
+        * @param s
+        *            the socket to bind to
+        */
+       public ConnectActionClientObject(Socket s) {
+               super(s);
+       }
+
+       /**
+        * Create a new {@link ConnectActionClientObject} with the current
+        * application version (see {@link Version#getCurrentVersion()}) as the
+        * client version.
+        * 
+        * @param host
+        *            the host to bind to
+        * @param port
+        *            the port to bind to
+        * @param ssl
+        *            TRUE for an SSL connection, FALSE for plain text
+        * 
+        * @throws IOException
+        *             in case of I/O error when creating the socket
+        */
+       public ConnectActionClientObject(String host, int port, boolean ssl)
+                       throws IOException {
+               super(host, port, ssl);
+       }
+
+       /**
+        * Create a new {@link ConnectActionClientObject}.
+        * 
+        * @param host
+        *            the host to bind to
+        * @param port
+        *            the port to bind to
+        * @param ssl
+        *            TRUE for an SSL connection, FALSE for plain text
+        * @param version
+        *            the client version
+        * 
+        * @throws IOException
+        *             in case of I/O error when creating the socket
+        */
+       public ConnectActionClientObject(String host, int port, boolean ssl,
+                       Version version) throws IOException {
+               super(host, port, ssl, version);
+       }
+
+       /**
+        * Create a new {@link ConnectActionClientObject}.
+        * 
+        * @param s
+        *            the socket to bind to
+        * @param version
+        *            the client version
+        */
+       public ConnectActionClientObject(Socket s, Version version) {
+               super(s, version);
+       }
+
+       /**
+        * Serialise and send the given object to the server (and return the
+        * deserialised answer).
+        * 
+        * @param data
+        *            the data to send
+        * 
+        * @return the answer, which can be NULL
+        * 
+        * @throws IOException
+        *             in case of I/O error
+        * @throws NoSuchFieldException
+        *             if the serialised data contains information about a field
+        *             which does actually not exist in the class we know of
+        * @throws NoSuchMethodException
+        *             if a class described in the serialised data cannot be created
+        *             because it is not compatible with this code
+        * @throws ClassNotFoundException
+        *             if a class described in the serialised data cannot be found
+        */
+       public Object send(Object data) throws IOException, NoSuchFieldException,
+                       NoSuchMethodException, ClassNotFoundException {
+               return action.sendObject(data);
+       }
+}
\ No newline at end of file
diff --git a/src/be/nikiroo/utils/serial/server/ConnectActionClientString.java b/src/be/nikiroo/utils/serial/server/ConnectActionClientString.java
new file mode 100644 (file)
index 0000000..f9402cb
--- /dev/null
@@ -0,0 +1,95 @@
+package be.nikiroo.utils.serial.server;
+
+import java.io.IOException;
+import java.net.Socket;
+
+import be.nikiroo.utils.Version;
+
+/**
+ * Class used for the client basic handling.
+ * <p>
+ * It represents a single action: a client is expected to only execute one
+ * action.
+ * 
+ * @author niki
+ */
+public class ConnectActionClientString extends ConnectActionClient {
+       /**
+        * Create a new {@link ConnectActionClientString} with the current
+        * application version (see {@link Version#getCurrentVersion()}) as the
+        * client version.
+        * 
+        * @param s
+        *            the socket to bind to
+        */
+       public ConnectActionClientString(Socket s) {
+               super(s);
+       }
+
+       /**
+        * Create a new {@link ConnectActionClientString} with the current
+        * application version (see {@link Version#getCurrentVersion()}) as the
+        * client version.
+        * 
+        * @param host
+        *            the host to bind to
+        * @param port
+        *            the port to bind to
+        * @param ssl
+        *            TRUE for an SSL connection, FALSE for plain text
+        * 
+        * @throws IOException
+        *             in case of I/O error when creating the socket
+        */
+       public ConnectActionClientString(String host, int port, boolean ssl)
+                       throws IOException {
+               super(host, port, ssl);
+       }
+
+       /**
+        * Create a new {@link ConnectActionClientString}.
+        * 
+        * @param host
+        *            the host to bind to
+        * @param port
+        *            the port to bind to
+        * @param ssl
+        *            TRUE for an SSL connection, FALSE for plain text
+        * @param version
+        *            the client version
+        * 
+        * @throws IOException
+        *             in case of I/O error when creating the socket
+        */
+       public ConnectActionClientString(String host, int port, boolean ssl,
+                       Version version) throws IOException {
+               super(host, port, ssl, version);
+       }
+
+       /**
+        * Create a new {@link ConnectActionClientString}.
+        * 
+        * @param s
+        *            the socket to bind to
+        * @param version
+        *            the client version
+        */
+       public ConnectActionClientString(Socket s, Version version) {
+               super(s, version);
+       }
+
+       /**
+        * Send the given object to the server (and return the answer).
+        * 
+        * @param data
+        *            the data to send
+        * 
+        * @return the answer, which can be NULL
+        * 
+        * @throws IOException
+        *             in case of I/O error
+        */
+       public String send(String data) throws IOException {
+               return action.sendString(data);
+       }
+}
\ No newline at end of file
similarity index 51%
rename from src/be/nikiroo/utils/serial/ConnectActionServer.java
rename to src/be/nikiroo/utils/serial/server/ConnectActionServer.java
index 2d85c79c86f41b2d7807bb3fcc3ad6b508a3cddc..85b46a2fdd89f594528d166f78e26a7177eb8e2c 100644 (file)
@@ -1,6 +1,5 @@
-package be.nikiroo.utils.serial;
+package be.nikiroo.utils.serial.server;
 
-import java.io.IOException;
 import java.net.Socket;
 
 import be.nikiroo.utils.Version;
@@ -13,8 +12,13 @@ import be.nikiroo.utils.Version;
  * 
  * @author niki
  */
-public class ConnectActionServer {
-       private ConnectAction action;
+abstract class ConnectActionServer {
+       /**
+        * The underlying {@link ConnectAction}.
+        * <p>
+        * Cannot be NULL.
+        */
+       protected ConnectAction action;
 
        /**
         * Create a new {@link ConnectActionServer} with the current application
@@ -86,51 +90,6 @@ public class ConnectActionServer {
        public void action(Version clientVersion) throws Exception {
        }
 
-       /**
-        * Serialise and send the given object to the client.
-        * 
-        * @param data
-        *            the data to send
-        * 
-        * @throws IOException
-        *             in case of I/O error
-        * @throws NoSuchFieldException
-        *             if the serialised data contains information about a field
-        *             which does actually not exist in the class we know of
-        * @throws NoSuchMethodException
-        *             if a class described in the serialised data cannot be created
-        *             because it is not compatible with this code
-        * @throws ClassNotFoundException
-        *             if a class described in the serialised data cannot be found
-        */
-       public void send(Object data) throws IOException, NoSuchFieldException,
-                       NoSuchMethodException, ClassNotFoundException {
-               action.send(data);
-       }
-
-       /**
-        * (Flush the data to the client if needed and) retrieve its answer.
-        * 
-        * @return the deserialised answer (which can actually be NULL)
-        * 
-        * @throws IOException
-        *             in case of I/O error
-        * @throws NoSuchFieldException
-        *             if the serialised data contains information about a field
-        *             which does actually not exist in the class we know of
-        * @throws NoSuchMethodException
-        *             if a class described in the serialised data cannot be created
-        *             because it is not compatible with this code
-        * @throws ClassNotFoundException
-        *             if a class described in the serialised data cannot be found
-        * @throws java.lang.NullPointerException
-        *             if the counter part has no data to send
-        */
-       public Object rec() throws NoSuchFieldException, NoSuchMethodException,
-                       ClassNotFoundException, IOException, java.lang.NullPointerException {
-               return action.rec();
-       }
-
        /**
         * Handler called when an unexpected error occurs in the code.
         * <p>
@@ -156,25 +115,4 @@ public class ConnectActionServer {
                        @SuppressWarnings("unused") Version clientVersion) {
                return action.getVersion();
        }
-
-       // old stuff:
-
-       /**
-        * Not used anymore. See {@link ConnectActionServer#rec()}.
-        */
-       @SuppressWarnings("javadoc")
-       @Deprecated
-       public Object flush() throws NoSuchFieldException, NoSuchMethodException,
-                       ClassNotFoundException, IOException, java.lang.NullPointerException {
-               return rec();
-       }
-
-       /**
-        * Not used anymore. See
-        * {@link ConnectActionServer#negotiateVersion(Version)}.
-        */
-       @SuppressWarnings({ "unused", "javadoc" })
-       @Deprecated
-       protected void onClientVersionReceived(Version clientVersion) {
-       }
 }
\ No newline at end of file
diff --git a/src/be/nikiroo/utils/serial/server/ConnectActionServerObject.java b/src/be/nikiroo/utils/serial/server/ConnectActionServerObject.java
new file mode 100644 (file)
index 0000000..e0e4276
--- /dev/null
@@ -0,0 +1,85 @@
+package be.nikiroo.utils.serial.server;
+
+import java.io.IOException;
+import java.net.Socket;
+
+import be.nikiroo.utils.Version;
+
+/**
+ * Class used for the server basic handling.
+ * <p>
+ * It represents a single action: a server is expected to execute one action for
+ * each client action.
+ * 
+ * @author niki
+ */
+public class ConnectActionServerObject extends ConnectActionServer {
+       /**
+        * Create a new {@link ConnectActionServerObject} with the current
+        * application version (see {@link Version#getCurrentVersion()}) as the
+        * server version.
+        * 
+        * @param s
+        *            the socket to bind to
+        */
+       public ConnectActionServerObject(Socket s) {
+               super(s);
+       }
+
+       /**
+        * Create a new {@link ConnectActionServerObject}.
+        * 
+        * @param s
+        *            the socket to bind to
+        * @param version
+        *            the server version
+        */
+       public ConnectActionServerObject(Socket s, Version version) {
+               super(s, version);
+       }
+
+       /**
+        * Serialise and send the given object to the client.
+        * 
+        * @param data
+        *            the data to send
+        * 
+        * @throws IOException
+        *             in case of I/O error
+        * @throws NoSuchFieldException
+        *             if the serialised data contains information about a field
+        *             which does actually not exist in the class we know of
+        * @throws NoSuchMethodException
+        *             if a class described in the serialised data cannot be created
+        *             because it is not compatible with this code
+        * @throws ClassNotFoundException
+        *             if a class described in the serialised data cannot be found
+        */
+       public void send(Object data) throws IOException, NoSuchFieldException,
+                       NoSuchMethodException, ClassNotFoundException {
+               action.sendObject(data);
+       }
+
+       /**
+        * (Flush the data to the client if needed and) retrieve its answer.
+        * 
+        * @return the deserialised answer (which can actually be NULL)
+        * 
+        * @throws IOException
+        *             in case of I/O error
+        * @throws NoSuchFieldException
+        *             if the serialised data contains information about a field
+        *             which does actually not exist in the class we know of
+        * @throws NoSuchMethodException
+        *             if a class described in the serialised data cannot be created
+        *             because it is not compatible with this code
+        * @throws ClassNotFoundException
+        *             if a class described in the serialised data cannot be found
+        * @throws java.lang.NullPointerException
+        *             if the counter part has no data to send
+        */
+       public Object rec() throws NoSuchFieldException, NoSuchMethodException,
+                       ClassNotFoundException, IOException, java.lang.NullPointerException {
+               return action.recObject();
+       }
+}
diff --git a/src/be/nikiroo/utils/serial/server/ConnectActionServerString.java b/src/be/nikiroo/utils/serial/server/ConnectActionServerString.java
new file mode 100644 (file)
index 0000000..35dd4dd
--- /dev/null
@@ -0,0 +1,65 @@
+package be.nikiroo.utils.serial.server;
+
+import java.io.IOException;
+import java.net.Socket;
+
+import be.nikiroo.utils.Version;
+
+/**
+ * Class used for the server basic handling.
+ * <p>
+ * It represents a single action: a server is expected to execute one action for
+ * each client action.
+ * 
+ * @author niki
+ */
+public class ConnectActionServerString extends ConnectActionServer {
+       /**
+        * Create a new {@link ConnectActionServerString} with the current
+        * application version (see {@link Version#getCurrentVersion()}) as the
+        * server version.
+        * 
+        * @param s
+        *            the socket to bind to
+        */
+       public ConnectActionServerString(Socket s) {
+               super(s);
+       }
+
+       /**
+        * Create a new {@link ConnectActionServerString}.
+        * 
+        * @param s
+        *            the socket to bind to
+        * @param version
+        *            the server version
+        */
+       public ConnectActionServerString(Socket s, Version version) {
+               super(s, version);
+       }
+
+       /**
+        * Serialise and send the given object to the client.
+        * 
+        * @param data
+        *            the data to send
+        * 
+        * @throws IOException
+        *             in case of I/O error
+        */
+       public void send(String data) throws IOException {
+               action.sendString(data);
+       }
+
+       /**
+        * (Flush the data to the client if needed and) retrieve its answer.
+        * 
+        * @return the answer if it is available, or NULL if not
+        * 
+        * @throws IOException
+        *             in case of I/O error
+        */
+       public String rec() throws IOException {
+               return action.recString();
+       }
+}
similarity index 82%
rename from src/be/nikiroo/utils/serial/Server.java
rename to src/be/nikiroo/utils/serial/server/Server.java
index 934be33786e27b1bbe159e39afce42cdbc373845..36806d6b61924bd60d5d0d1d2c6afca68d878893 100644 (file)
@@ -1,4 +1,4 @@
-package be.nikiroo.utils.serial;
+package be.nikiroo.utils.serial.server;
 
 import java.io.IOException;
 import java.net.ServerSocket;
@@ -12,7 +12,6 @@ import javax.net.ssl.SSLSocket;
 import javax.net.ssl.SSLSocketFactory;
 
 import be.nikiroo.utils.TraceHandler;
-import be.nikiroo.utils.Version;
 
 /**
  * This class implements a simple server that can listen for connections and
@@ -23,7 +22,7 @@ import be.nikiroo.utils.Version;
  * 
  * @author niki
  */
-abstract public class Server implements Runnable {
+abstract class Server implements Runnable {
        static private final String[] ANON_CIPHERS = getAnonCiphers();
 
        private final String name;
@@ -40,11 +39,15 @@ abstract public class Server implements Runnable {
 
        private TraceHandler tracer = new TraceHandler();
 
-       @Deprecated
-       public Server(@SuppressWarnings("unused") Version notUsed, int port,
-                       boolean ssl) throws IOException {
-               this(port, ssl);
-       }
+       /**
+        * Create a new {@link ConnectActionServer} to handle a request.
+        * 
+        * @param s
+        *            the socket to service
+        * 
+        * @return the action
+        */
+       abstract ConnectActionServer createConnectActionServer(Socket s);
 
        /**
         * Create a new server that will start listening on the network when
@@ -112,6 +115,17 @@ abstract public class Server implements Runnable {
                this.tracer = tracer;
        }
 
+       /**
+        * The name of this {@link Server} if any.
+        * <p>
+        * Used for traces and debug purposes only.
+        * 
+        * @return the name or NULL
+        */
+       public String getName() {
+               return name;
+       }
+
        /**
         * Return the assigned port.
         * 
@@ -171,35 +185,7 @@ abstract public class Server implements Runnable {
                        while (started && !exiting) {
                                count(1);
                                Socket s = ss.accept();
-                               new ConnectActionServer(s) {
-                                       @Override
-                                       public void action(Version clientVersion) throws Exception {
-                                               try {
-                                                       for (Object data = rec(); true; data = rec()) {
-                                                               Object rep = null;
-                                                               try {
-                                                                       rep = onRequest(this, clientVersion, data);
-                                                               } catch (Exception e) {
-                                                                       onError(e);
-                                                               }
-                                                               send(rep);
-                                                       }
-                                               } catch (NullPointerException e) {
-                                                       // Client has no data any more, we quit
-                                                       tracer.trace(name
-                                                                       + ": client has data no more, stopping connection");
-                                               }
-                                       }
-
-                                       @Override
-                                       public void connect() {
-                                               try {
-                                                       super.connect();
-                                               } finally {
-                                                       count(-1);
-                                               }
-                                       }
-                               }.connectAsync();
+                               createConnectActionServer(s).connectAsync();
                        }
 
                        // Will be covered by @link{Server#stop(long)} for timeouts
@@ -272,7 +258,7 @@ abstract public class Server implements Runnable {
                                exiting = true;
 
                                try {
-                                       new ConnectActionClient(createSocket(null, port, ssl))
+                                       new ConnectActionClientObject(createSocket(null, port, ssl))
                                                        .connect();
                                        long time = 0;
                                        while (ss != null && timeout > 0 && timeout > time) {
@@ -297,26 +283,6 @@ abstract public class Server implements Runnable {
                }
        }
 
-       /**
-        * This is the method that is called on each client request.
-        * <p>
-        * You are expected to react to it and return an answer (which can be NULL).
-        * 
-        * @param action
-        *            the client action
-        * @param clientVersion
-        *            the client version
-        * @param data
-        *            the data sent by the client (which can be NULL)
-        * 
-        * @return the answer to return to the client (which can be NULL)
-        * 
-        * @throws Exception
-        *             in case of an exception, the error will only be logged
-        */
-       abstract protected Object onRequest(ConnectActionServer action,
-                       Version clientVersion, Object data) throws Exception;
-
        /**
         * This method will be called on errors.
         * <p>
@@ -338,7 +304,7 @@ abstract public class Server implements Runnable {
         * 
         * @return the current number after this operation
         */
-       private int count(int change) {
+       int count(int change) {
                synchronized (counterLock) {
                        counter += change;
                        return counter;
diff --git a/src/be/nikiroo/utils/serial/server/ServerObject.java b/src/be/nikiroo/utils/serial/server/ServerObject.java
new file mode 100644 (file)
index 0000000..6ff81f5
--- /dev/null
@@ -0,0 +1,107 @@
+package be.nikiroo.utils.serial.server;
+
+import java.io.IOException;
+import java.net.Socket;
+
+import be.nikiroo.utils.Version;
+
+/**
+ * This class implements a simple server that can listen for connections and
+ * send/receive objects.
+ * <p>
+ * Note: this {@link ServerObject} has to be discarded after use (cannot be
+ * started twice).
+ * 
+ * @author niki
+ */
+abstract public class ServerObject extends Server {
+       /**
+        * Create a new server that will start listening on the network when
+        * {@link ServerObject#start()} is called.
+        * 
+        * @param port
+        *            the port to listen on, or 0 to assign any unallocated port
+        *            found (which can later on be queried via
+        *            {@link ServerObject#getPort()}
+        * @param ssl
+        *            use a SSL connection (or not)
+        * 
+        * @throws IOException
+        *             in case of I/O error
+        */
+       public ServerObject(int port, boolean ssl) throws IOException {
+               super(port, ssl);
+       }
+
+       /**
+        * Create a new server that will start listening on the network when
+        * {@link ServerObject#start()} is called.
+        * 
+        * @param name
+        *            the server name (only used for debug info and traces)
+        * @param port
+        *            the port to listen on
+        * @param ssl
+        *            use a SSL connection (or not)
+        * 
+        * @throws IOException
+        *             in case of I/O error
+        */
+       public ServerObject(String name, int port, boolean ssl) throws IOException {
+               super(name, port, ssl);
+       }
+
+       @Override
+       protected ConnectActionServer createConnectActionServer(Socket s) {
+               return new ConnectActionServerObject(s) {
+                       @Override
+                       public void action(Version clientVersion) throws Exception {
+                               try {
+                                       for (Object data = rec(); true; data = rec()) {
+                                               Object rep = null;
+                                               try {
+                                                       rep = onRequest(this, clientVersion, data);
+                                               } catch (Exception e) {
+                                                       onError(e);
+                                               }
+                                               send(rep);
+                                       }
+                               } catch (NullPointerException e) {
+                                       // Client has no data any more, we quit
+                                       getTraceHandler()
+                                                       .trace(getName()
+                                                                       + ": client has data no more, stopping connection");
+                               }
+                       }
+
+                       @Override
+                       public void connect() {
+                               try {
+                                       super.connect();
+                               } finally {
+                                       count(-1);
+                               }
+                       }
+               };
+       }
+
+       /**
+        * This is the method that is called on each client request.
+        * <p>
+        * You are expected to react to it and return an answer (which can be NULL).
+        * 
+        * @param action
+        *            the client action
+        * @param clientVersion
+        *            the client version
+        * @param data
+        *            the data sent by the client (which can be NULL)
+        * 
+        * @return the answer to return to the client (which can be NULL)
+        * 
+        * @throws Exception
+        *             in case of an exception, the error will only be logged
+        */
+       abstract protected Object onRequest(ConnectActionServerObject action,
+                       Version clientVersion, Object data) throws Exception;
+}
diff --git a/src/be/nikiroo/utils/serial/server/ServerString.java b/src/be/nikiroo/utils/serial/server/ServerString.java
new file mode 100644 (file)
index 0000000..4a185da
--- /dev/null
@@ -0,0 +1,113 @@
+package be.nikiroo.utils.serial.server;
+
+import java.io.IOException;
+import java.net.Socket;
+
+import be.nikiroo.utils.Version;
+
+/**
+ * This class implements a simple server that can listen for connections and
+ * send/receive Strings.
+ * <p>
+ * Note: this {@link ServerString} has to be discarded after use (cannot be
+ * started twice).
+ * 
+ * @author niki
+ */
+abstract public class ServerString extends Server {
+       /**
+        * Create a new server that will start listening on the network when
+        * {@link ServerString#start()} is called.
+        * 
+        * @param port
+        *            the port to listen on, or 0 to assign any unallocated port
+        *            found (which can later on be queried via
+        *            {@link ServerString#getPort()}
+        * @param ssl
+        *            use a SSL connection (or not)
+        * 
+        * @throws IOException
+        *             in case of I/O error
+        */
+       public ServerString(int port, boolean ssl) throws IOException {
+               super(port, ssl);
+       }
+
+       /**
+        * Create a new server that will start listening on the network when
+        * {@link ServerString#start()} is called.
+        * 
+        * @param name
+        *            the server name (only used for debug info and traces)
+        * @param port
+        *            the port to listen on
+        * @param ssl
+        *            use a SSL connection (or not)
+        * 
+        * @throws IOException
+        *             in case of I/O error
+        */
+       public ServerString(String name, int port, boolean ssl) throws IOException {
+               super(name, port, ssl);
+       }
+
+       @Override
+       protected ConnectActionServer createConnectActionServer(Socket s) {
+               return new ConnectActionServerString(s) {
+                       @Override
+                       public void action(Version clientVersion) throws Exception {
+                               try {
+                                       for (String data = rec(); data != null; data = rec()) {
+                                               String rep = null;
+                                               try {
+                                                       rep = onRequest(this, clientVersion, data);
+                                               } catch (Exception e) {
+                                                       onError(e);
+                                               }
+
+                                               if (rep == null) {
+                                                       rep = "";
+                                               }
+
+                                               send(rep);
+                                       }
+                               } catch (NullPointerException e) {
+                                       // Client has no data any more, we quit
+                                       getTraceHandler()
+                                                       .trace(getName()
+                                                                       + ": client has data no more, stopping connection");
+                               }
+                       }
+
+                       @Override
+                       public void connect() {
+                               try {
+                                       super.connect();
+                               } finally {
+                                       count(-1);
+                               }
+                       }
+               };
+       }
+
+       /**
+        * This is the method that is called on each client request.
+        * <p>
+        * You are expected to react to it and return an answer (NULL will be
+        * converted to an empty {@link String}).
+        * 
+        * @param action
+        *            the client action
+        * @param clientVersion
+        *            the client version
+        * @param data
+        *            the data sent by the client
+        * 
+        * @return the answer to return to the client
+        * 
+        * @throws Exception
+        *             in case of an exception, the error will only be logged
+        */
+       abstract protected String onRequest(ConnectActionServerString action,
+                       Version clientVersion, String data) throws Exception;
+}
index e3171c211e2bc91e17a0b046a3c00b284758b536..b1b5c8b53bc3a823f5cfd142c5d628a76122d314 100644 (file)
 package be.nikiroo.utils.test;
 
-import be.nikiroo.utils.TraceHandler;
 import be.nikiroo.utils.Version;
-import be.nikiroo.utils.serial.ConnectActionClient;
-import be.nikiroo.utils.serial.ConnectActionServer;
 import be.nikiroo.utils.serial.Exporter;
 import be.nikiroo.utils.serial.Importer;
-import be.nikiroo.utils.serial.Server;
+import be.nikiroo.utils.serial.server.ConnectActionClientObject;
+import be.nikiroo.utils.serial.server.ConnectActionClientString;
+import be.nikiroo.utils.serial.server.ConnectActionServerObject;
+import be.nikiroo.utils.serial.server.ConnectActionServerString;
+import be.nikiroo.utils.serial.server.ServerObject;
+import be.nikiroo.utils.serial.server.ServerString;
 
 class SerialTest extends TestLauncher {
        private SerialTest() {
                super("Serial test", null);
        }
 
-       private TestLauncher createServerTestCases(final String[] args,
+       private TestLauncher createServerStringTestCases(final String[] args,
+                       final boolean ssl) {
+               final String ssls = (ssl ? "(ssl)" : "(plain text)");
+               TestLauncher series = new TestLauncher("Client/Server " + ssls, args);
+
+               series.addTest(new TestCase("Simple connection " + ssls) {
+                       @Override
+                       public void test() throws Exception {
+                               final String[] rec = new String[1];
+
+                               ServerString server = new ServerString(this.getName(), 0, ssl) {
+                                       @Override
+                                       protected String onRequest(
+                                                       ConnectActionServerString action,
+                                                       Version clientVersion, String data)
+                                                       throws Exception {
+                                               return null;
+                                       }
+                               };
+
+                               assertEquals("A port should have been assigned", true,
+                                               server.getPort() > 0);
+
+                               server.start();
+
+                               try {
+                                       new ConnectActionClientObject(null, server.getPort(), ssl) {
+                                               @Override
+                                               public void action(Version serverVersion)
+                                                               throws Exception {
+                                                       rec[0] = "ok";
+                                               }
+                                       }.connect();
+                               } finally {
+                                       server.stop();
+                               }
+
+                               assertNotNull("The client action was not run", rec[0]);
+                               assertEquals("ok", rec[0]);
+                       }
+               });
+
+               series.addTest(new TestCase("Simple exchange " + ssls) {
+                       final String[] sent = new String[1];
+                       final String[] recd = new String[1];
+                       final Exception[] err = new Exception[1];
+
+                       @Override
+                       public void test() throws Exception {
+                               ServerString server = new ServerString(this.getName(), 0, ssl) {
+                                       @Override
+                                       protected String onRequest(
+                                                       ConnectActionServerString action,
+                                                       Version clientVersion, String data)
+                                                       throws Exception {
+                                               sent[0] = data;
+                                               return "pong";
+                                       }
+
+                                       @Override
+                                       protected void onError(Exception e) {
+                                               super.onError(e);
+                                               err[0] = e;
+                                       }
+                               };
+
+                               server.start();
+
+                               try {
+                                       new ConnectActionClientString(null, server.getPort(), ssl) {
+                                               @Override
+                                               public void action(Version serverVersion)
+                                                               throws Exception {
+                                                       recd[0] = send("ping");
+                                               }
+                                       }.connect();
+                               } finally {
+                                       server.stop();
+                               }
+
+                               if (err[0] != null) {
+                                       fail("An exception was thrown: " + err[0].getMessage());
+                               }
+
+                               assertEquals("ping", sent[0]);
+                               assertEquals("pong", recd[0]);
+                       }
+               });
+
+               series.addTest(new TestCase("Multiple exchanges " + ssls) {
+                       final String[] sent = new String[3];
+                       final String[] recd = new String[3];
+                       final Exception[] err = new Exception[1];
+
+                       @Override
+                       public void test() throws Exception {
+                               ServerString server = new ServerString(this.getName(), 0, ssl) {
+                                       @Override
+                                       protected String onRequest(
+                                                       ConnectActionServerString action,
+                                                       Version clientVersion, String data)
+                                                       throws Exception {
+                                               sent[0] = data;
+                                               action.send("pong");
+                                               sent[1] = action.rec();
+                                               return "pong2";
+                                       }
+
+                                       @Override
+                                       protected void onError(Exception e) {
+                                               super.onError(e);
+                                               err[0] = e;
+                                       }
+                               };
+
+                               server.start();
+
+                               try {
+                                       new ConnectActionClientString(null, server.getPort(), ssl) {
+                                               @Override
+                                               public void action(Version serverVersion)
+                                                               throws Exception {
+                                                       recd[0] = send("ping");
+                                                       recd[1] = send("ping2");
+                                               }
+                                       }.connect();
+                               } finally {
+                                       server.stop();
+                               }
+
+                               if (err[0] != null) {
+                                       fail("An exception was thrown: " + err[0].getMessage());
+                               }
+
+                               assertEquals("ping", sent[0]);
+                               assertEquals("pong", recd[0]);
+                               assertEquals("ping2", sent[1]);
+                               assertEquals("pong2", recd[1]);
+                       }
+               });
+
+               series.addTest(new TestCase("Multiple call from client " + ssls) {
+                       final String[] sent = new String[3];
+                       final String[] recd = new String[3];
+                       final Exception[] err = new Exception[1];
+
+                       @Override
+                       public void test() throws Exception {
+                               ServerString server = new ServerString(this.getName(), 0, ssl) {
+                                       @Override
+                                       protected String onRequest(
+                                                       ConnectActionServerString action,
+                                                       Version clientVersion, String data)
+                                                       throws Exception {
+                                               sent[Integer.parseInt(data)] = data;
+                                               return "" + (Integer.parseInt(data) * 2);
+                                       }
+
+                                       @Override
+                                       protected void onError(Exception e) {
+                                               super.onError(e);
+                                               err[0] = e;
+                                       }
+                               };
+
+                               server.start();
+
+                               try {
+                                       new ConnectActionClientString(null, server.getPort(), ssl) {
+                                               @Override
+                                               public void action(Version serverVersion)
+                                                               throws Exception {
+                                                       for (int i = 0; i < 3; i++) {
+                                                               recd[i] = send("" + i);
+                                                       }
+                                               }
+                                       }.connect();
+                               } finally {
+                                       server.stop();
+                               }
+
+                               if (err[0] != null) {
+                                       fail("An exception was thrown: " + err[0].getMessage());
+                               }
+
+                               assertEquals("0", sent[0]);
+                               assertEquals("0", recd[0]);
+                               assertEquals("1", sent[1]);
+                               assertEquals("2", recd[1]);
+                               assertEquals("2", sent[2]);
+                               assertEquals("4", recd[2]);
+                       }
+               });
+
+               return series;
+       }
+
+       private TestLauncher createServerObjectTestCases(final String[] args,
                        final boolean ssl) {
                final String ssls = (ssl ? "(ssl)" : "(plain text)");
                TestLauncher series = new TestLauncher("Client/Server " + ssls, args);
@@ -23,9 +222,10 @@ class SerialTest extends TestLauncher {
                        public void test() throws Exception {
                                final Object[] rec = new Object[1];
 
-                               Server server = new Server(this.getName(), 0, ssl) {
+                               ServerObject server = new ServerObject(this.getName(), 0, ssl) {
                                        @Override
-                                       protected Object onRequest(ConnectActionServer action,
+                                       protected Object onRequest(
+                                                       ConnectActionServerObject action,
                                                        Version clientVersion, Object data)
                                                        throws Exception {
                                                return null;
@@ -35,13 +235,10 @@ class SerialTest extends TestLauncher {
                                assertEquals("A port should have been assigned", true,
                                                server.getPort() > 0);
 
-                               // TODO: remove
-                               server.setTraceHandler(new TraceHandler(true, true, true));
-
                                server.start();
 
                                try {
-                                       new ConnectActionClient(null, server.getPort(), ssl) {
+                                       new ConnectActionClientObject(null, server.getPort(), ssl) {
                                                @Override
                                                public void action(Version serverVersion)
                                                                throws Exception {
@@ -64,9 +261,10 @@ class SerialTest extends TestLauncher {
 
                        @Override
                        public void test() throws Exception {
-                               Server server = new Server(this.getName(), 0, ssl) {
+                               ServerObject server = new ServerObject(this.getName(), 0, ssl) {
                                        @Override
-                                       protected Object onRequest(ConnectActionServer action,
+                                       protected Object onRequest(
+                                                       ConnectActionServerObject action,
                                                        Version clientVersion, Object data)
                                                        throws Exception {
                                                sent[0] = data;
@@ -83,7 +281,7 @@ class SerialTest extends TestLauncher {
                                server.start();
 
                                try {
-                                       new ConnectActionClient(null, server.getPort(), ssl) {
+                                       new ConnectActionClientObject(null, server.getPort(), ssl) {
                                                @Override
                                                public void action(Version serverVersion)
                                                                throws Exception {
@@ -110,9 +308,10 @@ class SerialTest extends TestLauncher {
 
                        @Override
                        public void test() throws Exception {
-                               Server server = new Server(this.getName(), 0, ssl) {
+                               ServerObject server = new ServerObject(this.getName(), 0, ssl) {
                                        @Override
-                                       protected Object onRequest(ConnectActionServer action,
+                                       protected Object onRequest(
+                                                       ConnectActionServerObject action,
                                                        Version clientVersion, Object data)
                                                        throws Exception {
                                                sent[0] = data;
@@ -131,7 +330,7 @@ class SerialTest extends TestLauncher {
                                server.start();
 
                                try {
-                                       new ConnectActionClient(null, server.getPort(), ssl) {
+                                       new ConnectActionClientObject(null, server.getPort(), ssl) {
                                                @Override
                                                public void action(Version serverVersion)
                                                                throws Exception {
@@ -161,9 +360,10 @@ class SerialTest extends TestLauncher {
 
                        @Override
                        public void test() throws Exception {
-                               Server server = new Server(this.getName(), 0, ssl) {
+                               ServerObject server = new ServerObject(this.getName(), 0, ssl) {
                                        @Override
-                                       protected Object onRequest(ConnectActionServer action,
+                                       protected Object onRequest(
+                                                       ConnectActionServerObject action,
                                                        Version clientVersion, Object data)
                                                        throws Exception {
                                                sent[(Integer) data] = data;
@@ -180,7 +380,7 @@ class SerialTest extends TestLauncher {
                                server.start();
 
                                try {
-                                       new ConnectActionClient(null, server.getPort(), ssl) {
+                                       new ConnectActionClientObject(null, server.getPort(), ssl) {
                                                @Override
                                                public void action(Version serverVersion)
                                                                throws Exception {
@@ -212,9 +412,13 @@ class SerialTest extends TestLauncher {
        public SerialTest(String[] args) {
                super("Serial test", args);
 
-               addSeries(createServerTestCases(args, false));
+               addSeries(createServerObjectTestCases(args, false));
+
+               addSeries(createServerObjectTestCases(args, true));
+
+               addSeries(createServerStringTestCases(args, false));
 
-               addSeries(createServerTestCases(args, true));
+               addSeries(createServerStringTestCases(args, true));
 
                addTest(new TestCase("Simple class Import/Export") {
                        @Override
index 490edbb4ec9d47db7f2c24cf21630ac303dc7044..9d0caaa9026ea16530360f57966ccaab584f6b45 100644 (file)
@@ -42,6 +42,7 @@ abstract public class TestCase {
         * @throws Exception
         *             in case of error
         */
+       @SuppressWarnings("unused")
        public void setUp() throws Exception {
        }
 
@@ -51,6 +52,7 @@ abstract public class TestCase {
         * @throws Exception
         *             in case of error
         */
+       @SuppressWarnings("unused")
        public void tearDown() throws Exception {
        }
 
index 62f3f6f38918941cc005aa2ece45ad5773d924e6..bee3071d7fce7a8689a1be50492b2ca28f729e68 100644 (file)
@@ -96,6 +96,7 @@ public class TestLauncher {
         * @throws Exception
         *             in case of error
         */
+       @SuppressWarnings("unused")
        protected void start() throws Exception {
        }
 
@@ -105,6 +106,7 @@ public class TestLauncher {
         * @throws Exception
         *             in case of error
         */
+       @SuppressWarnings("unused")
        protected void stop() throws Exception {
        }