Version 3.1.1: fixes: ServerBridge, Import/Export
authorNiki Roo <niki@nikiroo.be>
Wed, 29 Nov 2017 18:21:11 +0000 (19:21 +0100)
committerNiki Roo <niki@nikiroo.be>
Wed, 29 Nov 2017 18:21:11 +0000 (19:21 +0100)
VERSION
changelog.md
src/be/nikiroo/utils/serial/CustomSerializer.java
src/be/nikiroo/utils/serial/Importer.java
src/be/nikiroo/utils/serial/SerialUtils.java
src/be/nikiroo/utils/serial/server/ServerBridge.java
src/be/nikiroo/utils/test/SerialTest.java

diff --git a/VERSION b/VERSION
index fd2a01863fdd3035fac5918c59666363544bfe23..94ff29cc4de4fe0be04331a1eb51f5c515b728a9 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-3.1.0
+3.1.1
index 07ebcd443896b3037a385e5fba5374df36d0fd85..fa6415792878d181244ec912d58f3c0ea4d0e5c8 100644 (file)
@@ -1,5 +1,10 @@
 # nikiroo-utils
 
+## Version 3.1.1
+
+- Some fixes and trace handling changes in ServerBridge
+- Some fixes in Import/Export (objects serialisation)
+
 ## Version 3.1.0
 
 - New ServerBridge (including tests)
index fa03f02e141c5056df9ad8bc89f9d59937500a74..0bafb86f65152755ca7684614622af34e7aec449 100644 (file)
@@ -1,10 +1,12 @@
 package be.nikiroo.utils.serial;
 
+import java.io.IOException;
+
 public abstract class CustomSerializer {
 
        protected abstract String toString(Object value);
 
-       protected abstract Object fromString(String content);
+       protected abstract Object fromString(String content) throws IOException;
 
        protected abstract String getType();
 
@@ -30,7 +32,7 @@ public abstract class CustomSerializer {
                return true;
        }
 
-       public Object decode(String encodedValue) {
+       public Object decode(String encodedValue) throws IOException {
                return fromString((String) SerialUtils.decode(contentOf(encodedValue)));
        }
 
index a159ddedf4763859aefe8fc51ac82479d567ce0f..8fba42d7e78e112ddc85b017904ec21510abfe5a 100644 (file)
@@ -56,27 +56,33 @@ public class Importer {
         *             because it is not compatible with this code
         * @throws ClassNotFoundException
         *             if a class described in the serialised data cannot be found
+        * @throws IOException
+        *             if the content cannot be read (for instance, corrupt data)
         */
        public Importer read(String data) throws NoSuchFieldException,
-                       NoSuchMethodException, ClassNotFoundException {
+                       NoSuchMethodException, ClassNotFoundException, IOException {
 
+               Scanner scan = new Scanner(data);
                try {
-                       Scanner scan = new Scanner(data);
                        scan.useDelimiter("\n");
                        while (scan.hasNext()) {
                                String line = scan.next();
 
                                if (line.startsWith("ZIP:")) {
-                                       line = StringUtils.unzip64(line.substring("ZIP:".length()));
+                                       try {
+                                               line = StringUtils.unzip64(line.substring("ZIP:"
+                                                               .length()));
+                                       } catch (IOException e) {
+                                               throw new IOException(
+                                                               "Internal error when decoding ZIP content: input may be corrupt");
+                                       }
                                        read(line);
                                } else {
                                        processLine(line);
                                }
                        }
+               } finally {
                        scan.close();
-               } catch (IOException e) {
-                       throw new NoSuchMethodException(
-                                       "Internal error when decoding ZIP content: input may be corrupt");
                }
 
                return this;
@@ -99,9 +105,11 @@ public class Importer {
         *             because it is not compatible with this code
         * @throws ClassNotFoundException
         *             if a class described in the serialised data cannot be found
+        * @throws IOException
+        *             if the content cannot be read (for instance, corrupt data)
         */
        private boolean processLine(String line) throws NoSuchFieldException,
-                       NoSuchMethodException, ClassNotFoundException {
+                       NoSuchMethodException, ClassNotFoundException, IOException {
                // Defer to latest child if any
                if (child != null) {
                        if (child.processLine(line)) {
index 73f2027abb75480957beb087681495fa75009363..decf57525fb30336ab00dee5be5bb2952d5f8196 100644 (file)
@@ -85,7 +85,7 @@ public class SerialUtils {
                        }
 
                        @Override
-                       protected Object fromString(String content) {
+                       protected Object fromString(String content) throws IOException {
                                String[] tab = content.split("\n");
 
                                try {
@@ -98,7 +98,10 @@ public class SerialUtils {
 
                                        return array;
                                } catch (Exception e) {
-                                       throw new UnknownFormatConversionException(e.getMessage());
+                                       if (e instanceof IOException) {
+                                               throw (IOException) e;
+                                       }
+                                       throw new IOException(e.getMessage());
                                }
                        }
                });
@@ -326,24 +329,23 @@ public class SerialUtils {
         * 
         * @return the object (can be NULL for NULL encoded values)
         * 
-        * @throws UnknownFormatConversionException
+        * @throws IOException
         *             if the content cannot be converted
         */
-       static Object decode(String encodedValue) {
-               String cut = "";
-               if (encodedValue.length() > 1) {
-                       cut = encodedValue.substring(0, encodedValue.length() - 1);
-               }
-
+       static Object decode(String encodedValue) throws IOException {
                try {
+                       String cut = "";
+                       if (encodedValue.length() > 1) {
+                               cut = encodedValue.substring(0, encodedValue.length() - 1);
+                       }
+
                        if (CustomSerializer.isCustom(encodedValue)) {
                                // custom:TYPE_NAME:"content is String-encoded"
                                String type = CustomSerializer.typeOf(encodedValue);
                                if (customTypes.containsKey(type)) {
                                        return customTypes.get(type).decode(encodedValue);
                                }
-                               throw new UnknownFormatConversionException(
-                                               "Unknown custom type: " + type);
+                               throw new IOException("Unknown custom type: " + type);
                        } else if (encodedValue.equals("NULL")
                                        || encodedValue.equals("null")) {
                                return null;
@@ -371,10 +373,10 @@ public class SerialUtils {
                                return Integer.parseInt(encodedValue);
                        }
                } catch (Exception e) {
-                       if (e instanceof UnknownFormatConversionException) {
-                               throw (UnknownFormatConversionException) e;
+                       if (e instanceof IOException) {
+                               throw (IOException) e;
                        }
-                       throw new UnknownFormatConversionException(e.getMessage());
+                       throw new IOException(e.getMessage());
                }
        }
 
index 786d018ae00eaf38ee1ab55160ca05f0628c2003..b72c98ddd44fe45dcc0b8cb99f97565b4240e6b7 100644 (file)
@@ -1,8 +1,10 @@
 package be.nikiroo.utils.serial.server;
 
 import java.io.IOException;
+import java.lang.reflect.Array;
 import java.net.Socket;
 
+import be.nikiroo.utils.StringUtils;
 import be.nikiroo.utils.TraceHandler;
 import be.nikiroo.utils.Version;
 import be.nikiroo.utils.serial.Importer;
@@ -33,7 +35,13 @@ public class ServerBridge extends Server {
         *            found (which can later on be queried via
         *            {@link ServerBridge#getPort()}
         * @param ssl
-        *            use a SSL connection (or not)
+        *            use an SSL connection (or not)
+        * @param forwardToHost
+        *            the host server to forward the calls to
+        * @param forwardToPort
+        *            the host port to forward the calls to
+        * @param forwardToSsl
+        *            use an SSL connection for the forward server or not
         * 
         * @throws IOException
         *             in case of I/O error
@@ -55,7 +63,13 @@ public class ServerBridge extends Server {
         * @param port
         *            the port to listen on
         * @param ssl
-        *            use a SSL connection (or not)
+        *            use an SSL connection (or not)
+        * @param forwardToHost
+        *            the host server to forward the calls to
+        * @param forwardToPort
+        *            the host port to forward the calls to
+        * @param forwardToSsl
+        *            use an SSL connection for the forward server or not
         * 
         * @throws IOException
         *             in case of I/O error
@@ -72,13 +86,15 @@ public class ServerBridge extends Server {
        /**
         * The traces handler for this {@link Server}.
         * <p>
+        * The trace levels are handled as follow:
         * <ul>
-        * <li>At level 1, it will only print basic IN/OUT messages with length.</li>
-        * <li>At level 2, it will also print the data as a String.</li>
-        * <li>At level 3, it will try to interpret it (SLOW) and print the object
-        * type if possible.</li>
-        * <li>At level 4, it will try to print the {@link Object#toString()} value.
-        * </li>
+        * <li>1: it will only print basic IN/OUT messages with length</li>
+        * <li>2: it will try to interpret it as an object (SLOW) and print the
+        * object class if possible</li>
+        * <li>3: it will try to print the {@link Object#toString()} value, or the
+        * data if it is not an object</li>
+        * <li>4: it will also print the unzipped serialised value if it is an
+        * object</li>
         * </ul>
         * 
         * @param tracer
@@ -122,11 +138,9 @@ public class ServerBridge extends Server {
         * 
         * @param clientVersion
         *            the client version
-        * @param data
-        *            the data sent by the client
         */
        protected void onClientContact(Version clientVersion) {
-               getTraceHandler().trace("CLIENT " + clientVersion);
+               getTraceHandler().trace("<<< CLIENT " + clientVersion);
        }
 
        /**
@@ -134,11 +148,9 @@ public class ServerBridge extends Server {
         * 
         * @param serverVersion
         *            the server version
-        * @param data
-        *            the data sent by the client
         */
        protected void onServerContact(Version serverVersion) {
-               getTraceHandler().trace("SERVER " + serverVersion);
+               getTraceHandler().trace(">>> SERVER " + serverVersion);
        }
 
        /**
@@ -175,25 +187,69 @@ public class ServerBridge extends Server {
         *            the data to trace
         */
        private void trace(String prefix, String data) {
-               getTraceHandler().trace(prefix + ": " + data.length() + " characters",
-                               1);
+               int size = data.length();
+               String ssize = size + " byte";
+               if (size > 1) {
+                       ssize = size + " bytes";
+                       if (size >= 1000) {
+                               size = size / 1000;
+                               ssize = size + " kb";
+                               if (size > 1000) {
+                                       size = size / 1000;
+                                       ssize = size + " MB";
+                               }
+                       }
+               }
+
+               getTraceHandler().trace(prefix + ": " + ssize, 1);
 
                if (getTraceHandler().getTraceLevel() >= 2) {
                        try {
+                               if (data.startsWith("ZIP:")) {
+                                       data = StringUtils.unzip64(data.substring(4));
+                               }
+
                                Object obj = new Importer().read(data).getValue();
                                if (obj == null) {
+                                       getTraceHandler().trace("NULL", 2);
                                        getTraceHandler().trace("NULL", 3);
                                        getTraceHandler().trace("NULL", 4);
                                } else {
-                                       getTraceHandler().trace("(" + obj.getClass() + ")", 3);
-                                       getTraceHandler().trace("" + obj.toString(), 4);
+                                       if (obj.getClass().isArray()) {
+                                               getTraceHandler().trace(
+                                                               "(" + obj.getClass() + ") with "
+                                                                               + Array.getLength(obj) + "element(s)",
+                                                               3);
+                                       } else {
+                                               getTraceHandler().trace("(" + obj.getClass() + ")", 2);
+                                       }
+                                       getTraceHandler().trace("" + obj.toString(), 3);
+                                       getTraceHandler().trace(data, 4);
                                }
+                       } catch (NoSuchMethodException e) {
+                               getTraceHandler().trace("(not an object)", 2);
+                               getTraceHandler().trace(data, 3);
+                               getTraceHandler().trace("", 4);
+                       } catch (NoSuchFieldException e) {
+                               getTraceHandler().trace(
+                                               "(object known but incompatible: " + e.getMessage()
+                                                               + ")", 2);
+                               getTraceHandler().trace(data, 3);
+                               getTraceHandler().trace("", 4);
+                       } catch (ClassNotFoundException e) {
+                               getTraceHandler().trace(
+                                               "(unknown object: " + e.getMessage() + ")", 2);
+                               getTraceHandler().trace(data, 3);
+                               getTraceHandler().trace("", 4);
                        } catch (Exception e) {
-                               getTraceHandler().trace("(not an object)", 3);
-                               getTraceHandler().trace(data, 4);
+                               getTraceHandler()
+                                               .trace("(error when trying to decode: "
+                                                               + e.getMessage() + ")", 2);
+                               getTraceHandler().trace(data, 3);
+                               getTraceHandler().trace("", 4);
                        }
 
-                       getTraceHandler().trace("", 4);
+                       getTraceHandler().trace("", 2);
                }
        }
 
@@ -205,10 +261,10 @@ public class ServerBridge extends Server {
         *            <ul>
         *            <li>The bridge name</li>
         *            <li>The bridge port</li>
-        *            <li>TRUE for a ssl bridge, FALSE for plain text</li>
+        *            <li>TRUE for an SSL bridge, FALSE for plain text</li>
         *            <li>The forward server host</li>
         *            <li>The forward server port</li>
-        *            <li>TRUE for a ssl forward server, FALSE for plain text</li>
+        *            <li>TRUE for an SSL forward server, FALSE for plain text</li>
         *            <li>(optional) a trace level</li>
         *            </ul>
         */
index bb62144ac94ebe8781ce4470a949c2a56fe6e763..b203c2a73f96ed3a1d52fba784bb428f47632778 100644 (file)
@@ -4,6 +4,13 @@ import be.nikiroo.utils.serial.Exporter;
 import be.nikiroo.utils.serial.Importer;
 
 class SerialTest extends TestLauncher {
+       /**
+        * Required for Import/Export of objects.
+        */
+       public SerialTest() {
+               this(null);
+       }
+
        public SerialTest(String[] args) {
                super("Serial test", args);