Performance improvement:
[jvcard.git] / src / be / nikiroo / jvcard / remote / SimpleSocket.java
index e35189bce4e2a7a269a34a851e9332374709f135..264fff5c68b458e6a12e45c315da306cb0b04f1e 100644 (file)
@@ -1,6 +1,7 @@
 package be.nikiroo.jvcard.remote;
 
 import java.io.BufferedReader;
+import java.io.Closeable;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.PrintWriter;
@@ -10,8 +11,6 @@ import java.util.Arrays;
 import java.util.LinkedList;
 import java.util.List;
 
-import be.nikiroo.jvcard.remote.Command.Verb;
-
 /**
  * A client or server connection, that will allow you to connect to, send and
  * receive data to/from a jVCard remote server.
@@ -21,10 +20,57 @@ import be.nikiroo.jvcard.remote.Command.Verb;
  * @author niki
  */
 public class SimpleSocket {
+       /**
+        * An {@link Appendable} that can be used to send data over a
+        * {@link SimpleSocket}. You must close it to send the end of block element.
+        * 
+        * @author niki
+        *
+        */
+       public class BlockAppendable implements Appendable, Closeable {
+               private SimpleSocket ss;
+
+               /**
+                * Create a new {@link BlockAppendable} for the given
+                * {@link SimpleSocket}.
+                * 
+                * @param ss
+                *            the {@link SimpleSocket}
+                */
+               public BlockAppendable(SimpleSocket ss) {
+                       this.ss = ss;
+               }
+
+               @Override
+               public Appendable append(CharSequence csq) throws IOException {
+                       ss.send(csq);
+                       return this;
+               }
+
+               @Override
+               public Appendable append(char c) throws IOException {
+                       ss.send("" + c);
+                       return this;
+               }
+
+               @Override
+               public Appendable append(CharSequence csq, int start, int end)
+                               throws IOException {
+                       ss.send(csq.subSequence(start, end));
+                       return this;
+               }
+
+               @Override
+               public void close() throws IOException {
+                       ss.sendBlock();
+               }
+
+       }
+
        /**
         * The current version of the network protocol.
         */
-       static private final int CURRENT_VERSION = 1;
+       static public final int CURRENT_VERSION = 1;
 
        /**
         * The end of block marker.
@@ -83,17 +129,18 @@ public class SimpleSocket {
                in = new BufferedReader(new InputStreamReader(s.getInputStream()));
 
                if (client) {
-                       version = new Command(receiveLine(), -1).getVersion();
-                       sendLine(new Command(Command.Verb.VERSION, CURRENT_VERSION)
+                       version = new CommandInstance(receiveLine(), -1).getVersion();
+                       sendLine(new CommandInstance(Command.VERSION, CURRENT_VERSION)
                                        .toString());
                } else {
-                       send(new Command(Command.Verb.VERSION, CURRENT_VERSION).toString());
+                       send(new CommandInstance(Command.VERSION, CURRENT_VERSION)
+                                       .toString());
                        // TODO: i18n
                        send("[Some help info here]");
                        send("you need to reply with your VERSION + end of block");
                        send("please send HELP in a full block or help");
                        sendBlock();
-                       version = new Command(receiveLine(), -1).getVersion();
+                       version = new CommandInstance(receiveLine(), -1).getVersion();
                }
        }
 
@@ -133,7 +180,7 @@ public class SimpleSocket {
        }
 
        /**
-        * Sends commands to the remote server. Do <b>NOT</b> sends the end-of-block
+        * Sends lines to the remote server. Do <b>NOT</b> sends the end-of-block
         * marker.
         * 
         * @param data
@@ -142,12 +189,12 @@ public class SimpleSocket {
         * @throws IOException
         *             in case of IO error
         */
-       protected void send(String data) throws IOException {
+       protected void send(CharSequence data) throws IOException {
                if (data != null) {
-                       out.write(data);
+                       out.append(data);
                }
 
-               out.write("\n");
+               out.append("\n");
 
                if (out.checkError())
                        throw new IOException();
@@ -198,20 +245,20 @@ public class SimpleSocket {
        /**
         * Sends commands to the remote server, then sends an end-of-block marker.
         * 
-        * @param verb
-        *            the {@link Verb} to send
+        * @param command
+        *            the {@link Command} to send
         * 
         * @throws IOException
         *             in case of IO error
         */
-       public void sendCommand(Command.Verb verb) throws IOException {
-               sendCommand(verb, null);
+       public void sendCommand(Command command) throws IOException {
+               sendCommand(command, null);
        }
 
        /**
         * Sends commands to the remote server, then sends an end-of-block marker.
         * 
-        * @param verb
+        * @param command
         *            the data to send
         * 
         * @param param
@@ -220,8 +267,20 @@ public class SimpleSocket {
         * @throws IOException
         *             in case of IO error
         */
-       public void sendCommand(Command.Verb verb, String param) throws IOException {
-               sendLine(new Command(verb, param, CURRENT_VERSION).toString());
+       public void sendCommand(Command command, String param) throws IOException {
+               sendLine(new CommandInstance(command, param, CURRENT_VERSION)
+                               .toString());
+       }
+
+       /**
+        * Create a new {@link Appendable} that can be used to send data on this
+        * {@link SimpleSocket}. When you are done, just call
+        * {@link BlockAppendable#close()}.
+        * 
+        * @return the {@link Appendable}
+        */
+       public BlockAppendable createBlockAppendable() {
+               return new BlockAppendable(this);
        }
 
        /**
@@ -283,17 +342,17 @@ public class SimpleSocket {
        }
 
        /**
-        * Read a line from the remote server and convert it to a {@link Command},
-        * then read until the next end-of-block marker.
+        * Read a line from the remote server and convert it to a
+        * {@link CommandInstance}, then read until the next end-of-block marker.
         * 
-        * @return the parsed {@link Command}
+        * @return the parsed {@link CommandInstance}
         * 
         * @throws IOException
         *             in case of IO error
         */
-       public Command receiveCommand() throws IOException {
+       public CommandInstance receiveCommand() throws IOException {
                String line = receive();
-               Command cmd = new Command(line, version);
+               CommandInstance cmd = new CommandInstance(line, version);
                receiveBlock();
                return cmd;
        }