Author: markt
Date: Sat Mar  9 19:14:18 2013
New Revision: 1454758

URL: http://svn.apache.org/r1454758
Log:
Get encoding and decoding working end to end with an associated unit test

Added:
    tomcat/trunk/test/org/apache/tomcat/websocket/pojo/
    
tomcat/trunk/test/org/apache/tomcat/websocket/pojo/TestEncodingDecoding.java   
(with props)
Modified:
    tomcat/trunk/java/org/apache/tomcat/websocket/LocalStrings.properties
    tomcat/trunk/java/org/apache/tomcat/websocket/Util.java
    tomcat/trunk/java/org/apache/tomcat/websocket/WsWebSocketContainer.java
    tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoEndpointClient.java
    tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMethodMapping.java
    tomcat/trunk/java/org/apache/tomcat/websocket/server/LocalStrings.properties
    tomcat/trunk/java/org/apache/tomcat/websocket/server/WsServerContainer.java

Modified: tomcat/trunk/java/org/apache/tomcat/websocket/LocalStrings.properties
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/LocalStrings.properties?rev=1454758&r1=1454757&r2=1454758&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/LocalStrings.properties 
(original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/LocalStrings.properties Sat 
Mar  9 19:14:18 2013
@@ -62,5 +62,6 @@ wsWebSocketContainer.invalidHeader=Unabl
 wsWebSocketContainer.invalidStatus=The HTTP response from the server [{0}] did 
not permit the HTTP upgrade to WebSocket
 wsWebSocketContainer.invalidSubProtocol=The WebSocket server returned multiple 
values for the Sec-WebSocket-Protocol header
 wsWebSocketContainer.maxBuffer=This implementation limits the maximum size of 
a buffer to Integer.MAX_VALUE
+wsWebSocketContainer.missingAnnotation=Cannot use POJO class [{0}] as it is 
not annotated with @ClientEndpoint
 wsWebSocketContainer.pathNoHost=No host was specified in URI
 wsWebSocketContainer.pathWrongScheme=The scheme [{0}] is not supported
\ No newline at end of file

Modified: tomcat/trunk/java/org/apache/tomcat/websocket/Util.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/Util.java?rev=1454758&r1=1454757&r2=1454758&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/Util.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/Util.java Sat Mar  9 19:14:18 
2013
@@ -26,6 +26,7 @@ import java.util.concurrent.ConcurrentLi
 
 import javax.websocket.CloseReason.CloseCode;
 import javax.websocket.CloseReason.CloseCodes;
+import javax.websocket.Decoder;
 import javax.websocket.Encoder;
 import javax.websocket.MessageHandler;
 
@@ -33,7 +34,7 @@ import javax.websocket.MessageHandler;
  * Utility class for internal use only within the
  * {@link org.apache.tomcat.websocket} package.
  */
-class Util {
+public class Util {
 
     private static final Queue<SecureRandom> randoms =
             new ConcurrentLinkedQueue<>();
@@ -142,6 +143,11 @@ class Util {
     }
 
 
+    public static Class<?> getDecoderType(Class<? extends Decoder> Decoder) {
+        return (Class<?>) Util.getGenericType(Decoder.class, Decoder);
+    }
+
+
     static Class<?> getEncoderType(Class<? extends Encoder> encoder) {
         return (Class<?>) Util.getGenericType(Encoder.class, encoder);
     }

Modified: 
tomcat/trunk/java/org/apache/tomcat/websocket/WsWebSocketContainer.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/WsWebSocketContainer.java?rev=1454758&r1=1454757&r2=1454758&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/WsWebSocketContainer.java 
(original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/WsWebSocketContainer.java Sat 
Mar  9 19:14:18 2013
@@ -24,6 +24,7 @@ import java.nio.ByteBuffer;
 import java.nio.channels.AsynchronousSocketChannel;
 import java.nio.charset.Charset;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -80,7 +81,15 @@ public class WsWebSocketContainer
     public Session connectToServer(Object pojo, URI path)
             throws DeploymentException {
 
-        Endpoint ep = new PojoEndpointClient(pojo);
+        ClientEndpoint annotation =
+                pojo.getClass().getAnnotation(ClientEndpoint.class);
+        if (annotation == null) {
+            throw new DeploymentException(
+                    sm.getString("wsWebSocketContainer.missingAnnotation",
+                            pojo.getClass().getName()));
+        }
+
+        Endpoint ep = new PojoEndpointClient(pojo, annotation.decoders());
 
         Class<? extends ClientEndpointConfig.Configurator> configuratorClazz =
                 pojo.getClass().getAnnotation(
@@ -97,9 +106,11 @@ public class WsWebSocketContainer
             }
         }
 
-        ClientEndpointConfig config =
-                ClientEndpointConfig.Builder.create().configurator(
-                        configurator).build();
+        ClientEndpointConfig config = ClientEndpointConfig.Builder.create().
+                configurator(configurator).
+                decoders(Arrays.asList(annotation.decoders())).
+                encoders(Arrays.asList(annotation.encoders())).
+                build();
         return connectToServer(ep, config, path);
     }
 

Modified: 
tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoEndpointClient.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoEndpointClient.java?rev=1454758&r1=1454757&r2=1454758&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoEndpointClient.java 
(original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoEndpointClient.java 
Sat Mar  9 19:14:18 2013
@@ -18,15 +18,19 @@ package org.apache.tomcat.websocket.pojo
 
 import java.util.Collections;
 
+import javax.websocket.Decoder;
+import javax.websocket.DeploymentException;
 import javax.websocket.EndpointConfig;
 import javax.websocket.Session;
 
 
 public class PojoEndpointClient extends PojoEndpointBase {
 
-    public PojoEndpointClient(Object pojo) {
+    public PojoEndpointClient(Object pojo,
+            Class<? extends Decoder>[] decoders) throws DeploymentException {
         setPojo(pojo);
-        setMethodMapping(new PojoMethodMapping(pojo.getClass(), null));
+        setMethodMapping(
+                new PojoMethodMapping(pojo.getClass(), decoders, null));
         setPathParameters(Collections.EMPTY_MAP);
     }
 

Modified: 
tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMethodMapping.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMethodMapping.java?rev=1454758&r1=1454757&r2=1454758&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMethodMapping.java 
(original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMethodMapping.java 
Sat Mar  9 19:14:18 2013
@@ -19,11 +19,17 @@ package org.apache.tomcat.websocket.pojo
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
 import java.nio.ByteBuffer;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import javax.websocket.Decoder;
+import javax.websocket.Decoder.Binary;
+import javax.websocket.Decoder.BinaryStream;
+import javax.websocket.DeploymentException;
 import javax.websocket.EndpointConfig;
 import javax.websocket.MessageHandler;
 import javax.websocket.OnClose;
@@ -34,6 +40,9 @@ import javax.websocket.PongMessage;
 import javax.websocket.Session;
 import javax.websocket.server.PathParam;
 
+import org.apache.tomcat.util.res.StringManager;
+import org.apache.tomcat.websocket.Util;
+
 /**
  * For a POJO class annotated with
  * {@link javax.websocket.server.ServerEndpoint}, an instance of this class
@@ -42,6 +51,9 @@ import javax.websocket.server.PathParam;
  */
 public class PojoMethodMapping {
 
+    private static final StringManager sm =
+            StringManager.getManager(Constants.PACKAGE_NAME);
+
     private final Method onOpen;
     private final Method onClose;
     private final Method onError;
@@ -52,8 +64,13 @@ public class PojoMethodMapping {
     private final String wsPath;
 
 
-    public PojoMethodMapping(Class<?> clazzPojo, String wsPath) {
+    public PojoMethodMapping(Class<?> clazzPojo,
+            Class<? extends Decoder>[] decoderClazzes, String wsPath)
+                    throws DeploymentException {
+
         this.wsPath = wsPath;
+
+        List<DecoderEntry> decoders = getDecoders(decoderClazzes);
         Method open = null;
         Method close = null;
         Method error = null;
@@ -68,7 +85,7 @@ public class PojoMethodMapping {
                     method.getAnnotation(OnError.class) != null) {
                 error = method;
             } else if (method.getAnnotation(OnMessage.class) != null) {
-                onMessage.add(new MessageMethod(method));
+                onMessage.add(new MessageMethod(method, decoders));
             }
         }
         this.onOpen = open;
@@ -130,6 +147,29 @@ public class PojoMethodMapping {
     }
 
 
+    private static List<DecoderEntry> getDecoders(
+            Class<? extends Decoder>[] decoderClazzes)
+                    throws DeploymentException{
+
+        List<DecoderEntry> result = new ArrayList<>();
+        for (Class<? extends Decoder> decoderClazz : decoderClazzes) {
+            Decoder instance;
+            try {
+                instance = decoderClazz.newInstance();
+            } catch (InstantiationException | IllegalAccessException e) {
+                throw new DeploymentException(
+                        sm.getString("wsRemoteEndpoint.invalidEncoder",
+                                decoderClazz.getName()), e);
+            }
+            DecoderEntry entry = new DecoderEntry(
+                    Util.getDecoderType(decoderClazz), instance);
+            result.add(entry);
+        }
+
+        return result;
+    }
+
+
     private static PojoPathParam[] getPathParams(Method m, boolean isError) {
         if (m == null) {
             return new PojoPathParam[0];
@@ -232,7 +272,7 @@ public class PojoMethodMapping {
         private int indexPayload = -1;
 
 
-        public MessageMethod(Method m) {
+        public MessageMethod(Method m, List<DecoderEntry> decoderEntries) {
             this.m = m;
 
             Class<?>[] types = m.getParameterTypes();
@@ -291,6 +331,31 @@ public class PojoMethodMapping {
                         // TODO i18n
                         throw new IllegalArgumentException();
                     }
+                } else {
+                    for (DecoderEntry decoderEntry : decoderEntries) {
+                        if (decoderEntry.getClazz().isAssignableFrom(
+                                types[i])) {
+                            if (Binary.class.isAssignableFrom(
+                                        decoderEntry.getDecoder().getClass()) 
||
+                                    BinaryStream.class.isAssignableFrom(
+                                            
decoderEntry.getDecoder().getClass())) {
+                                if (indexByteBuffer == -1) {
+                                    indexByteBuffer = i;
+                                } else {
+                                    // TODO i18n
+                                    throw new IllegalArgumentException();
+                                }
+                                break;
+                            } else {
+                                if (indexString == -1) {
+                                    indexString = i;
+                                } else {
+                                    // TODO i18n
+                                    throw new IllegalArgumentException();
+                                }
+                            }
+                        }
+                    }
                 }
             }
             // Additional checks required
@@ -384,4 +449,24 @@ public class PojoMethodMapping {
             return mh;
         }
     }
+
+
+    private static class DecoderEntry {
+
+        private final Class<?> clazz;
+        private final Decoder decoder;
+
+        public DecoderEntry(Class<?> clazz, Decoder decoder) {
+            this.clazz = clazz;
+            this.decoder = decoder;
+        }
+
+        public Class<?> getClazz() {
+            return clazz;
+        }
+
+        public Decoder getDecoder() {
+            return decoder;
+        }
+    }
 }

Modified: 
tomcat/trunk/java/org/apache/tomcat/websocket/server/LocalStrings.properties
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/server/LocalStrings.properties?rev=1454758&r1=1454757&r2=1454758&view=diff
==============================================================================
--- 
tomcat/trunk/java/org/apache/tomcat/websocket/server/LocalStrings.properties 
(original)
+++ 
tomcat/trunk/java/org/apache/tomcat/websocket/server/LocalStrings.properties 
Sat Mar  9 19:14:18 2013
@@ -13,12 +13,17 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 sci.newInstance.fail=Failed to create an Endpoint instance of type [{0}]
+
+serverContainer.configuratorFail=Failed to create configurator of type [{0}] 
for POJO of type [{1}]
 serverContainer.endpointDeploy=Endpoint class [{0}] deploying to path [{1}] in 
ServletContext [{2}]
 serverContainer.missingAnnotation=Cannot deploy POJO class [{0}] as it is not 
annotated with @ServerEndpoint
 serverContainer.missingEndpoint=An Endpoint instance has been request for path 
[{0}] but no matching Endpoint class was found
 serverContainer.pojoDeploy=POJO class [{0}] deploying to path [{1}] in 
ServletContext [{2}]
 serverContainer.servletContextMismatch=Attempted to register a POJO annotated 
for WebSocket at path [{0}] in the ServletContext with context path [{1}] when 
the WebSocket ServerContainer is allocated to the ServletContext with context 
path [{2}]
 serverContainer.servletContextMissing=No ServletContext was specified
+
 uriTemplate.noMatch=The input template [{0}] generated the pattern [{1}] which 
did not match the supplied pathInfo [{2}]
+
 wsProtocolHandler.closeFailed=Failed to close the WebSocket connection cleanly
+
 wsRemoteEndpointServer.closeFailed=Failed to close the ServletOutputStream 
connection cleanly
\ No newline at end of file

Modified: 
tomcat/trunk/java/org/apache/tomcat/websocket/server/WsServerContainer.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/server/WsServerContainer.java?rev=1454758&r1=1454757&r2=1454758&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/server/WsServerContainer.java 
(original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/server/WsServerContainer.java 
Sat Mar  9 19:14:18 2013
@@ -16,6 +16,7 @@
  */
 package org.apache.tomcat.websocket.server;
 
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.Map;
 import java.util.WeakHashMap;
@@ -27,6 +28,7 @@ import javax.websocket.DeploymentExcepti
 import javax.websocket.server.ServerContainer;
 import javax.websocket.server.ServerEndpoint;
 import javax.websocket.server.ServerEndpointConfig;
+import javax.websocket.server.ServerEndpointConfig.Configurator;
 
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
@@ -181,7 +183,8 @@ public class WsServerContainer extends W
         }
 
         pojoMap.put(mapPath, pojo);
-        pojoMethodMap.put(pojo, new PojoMethodMapping(pojo, wsPath));
+        pojoMethodMap.put(pojo,
+                new PojoMethodMapping(pojo, annotation.decoders(), wsPath));
         addWsServletMapping(servletPath);
     }
 
@@ -205,14 +208,31 @@ public class WsServerContainer extends W
         }
         Class<?> pojo = pojoMap.get(servletPath);
         if (pojo != null) {
+            ServerEndpoint annotation =
+                    pojo.getAnnotation(ServerEndpoint.class);
             PojoMethodMapping methodMapping = pojoMethodMap.get(pojo);
             if (methodMapping != null) {
+                Configurator configurator;
+                try {
+                    configurator = annotation.configurator().newInstance();
+                } catch (InstantiationException | IllegalAccessException e) {
+                    throw new IllegalStateException(sm.getString(
+                            "serverContainer.configuratorFail",
+                            annotation.configurator().getName(),
+                            pojo.getClass().getName()), e);
+                }
                 sec = ServerEndpointConfig.Builder.create(
-                        pojo, methodMapping.getWsPath()).build();
+                        pojo, methodMapping.getWsPath()).
+                        decoders(Arrays.asList(annotation.decoders())).
+                        encoders(Arrays.asList(annotation.encoders())).
+                        configurator(configurator).
+                        build();
                 sec.getUserProperties().put(
-                        PojoEndpointServer.POJO_PATH_PARAM_KEY, 
pathParameters);
+                        PojoEndpointServer.POJO_PATH_PARAM_KEY,
+                        pathParameters);
                 sec.getUserProperties().put(
-                        PojoEndpointServer.POJO_METHOD_MAPPING_KEY, 
methodMapping);
+                        PojoEndpointServer.POJO_METHOD_MAPPING_KEY,
+                        methodMapping);
                 return sec;
             }
         }

Added: 
tomcat/trunk/test/org/apache/tomcat/websocket/pojo/TestEncodingDecoding.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/tomcat/websocket/pojo/TestEncodingDecoding.java?rev=1454758&view=auto
==============================================================================
--- 
tomcat/trunk/test/org/apache/tomcat/websocket/pojo/TestEncodingDecoding.java 
(added)
+++ 
tomcat/trunk/test/org/apache/tomcat/websocket/pojo/TestEncodingDecoding.java 
Sat Mar  9 19:14:18 2013
@@ -0,0 +1,251 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.tomcat.websocket.pojo;
+
+import java.net.URI;
+import java.nio.ByteBuffer;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+import javax.servlet.ServletContextEvent;
+import javax.websocket.ClientEndpoint;
+import javax.websocket.ContainerProvider;
+import javax.websocket.DecodeException;
+import javax.websocket.Decoder;
+import javax.websocket.DeploymentException;
+import javax.websocket.EncodeException;
+import javax.websocket.Encoder;
+import javax.websocket.OnMessage;
+import javax.websocket.Session;
+import javax.websocket.WebSocketContainer;
+import javax.websocket.server.ServerEndpoint;
+import javax.websocket.server.ServerEndpointConfig.Configurator;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.startup.Tomcat;
+import org.apache.catalina.startup.TomcatBaseTest;
+import org.apache.tomcat.websocket.server.WsListener;
+import org.apache.tomcat.websocket.server.WsServerContainer;
+
+public class TestEncodingDecoding extends TomcatBaseTest {
+
+    private static final String MESSAGE_ONE = "message-one";
+
+    @Test
+    public void test() throws Exception {
+        Tomcat tomcat = getTomcatInstance();
+        // Must have a real docBase - just use temp
+        Context ctx =
+            tomcat.addContext("", System.getProperty("java.io.tmpdir"));
+        ctx.addApplicationListener(ServerConfigListener.class.getName());
+
+        WebSocketContainer wsContainer =
+                ContainerProvider.getWebSocketContainer();
+
+        tomcat.start();
+
+        Client client = new Client();
+        URI uri = new URI("http://localhost:"; + getPort() + "/");
+        Session session = wsContainer.connectToServer(client, uri);
+
+        MsgString msg1 = new MsgString();
+        msg1.setData(MESSAGE_ONE);
+        session.getBasicRemote().sendObject(msg1);
+
+        Server server = ServerConfigurator.getServerInstance();
+
+        // Should not take very long
+        int i = 0;
+        while (i < 20) {
+            if (server.received.size() > 0 && client.received.size() > 0) {
+                break;
+            }
+            Thread.sleep(100);
+        }
+
+        // Check messages were received
+        Assert.assertEquals(1, server.received.size());
+        Assert.assertEquals(1, client.received.size());
+
+        // Check correct messages were received
+        Assert.assertEquals(MESSAGE_ONE,
+                ((MsgString) server.received.peek()).getData());
+        Assert.assertEquals(MESSAGE_ONE,
+                ((MsgString) client.received.peek()).getData());
+    }
+
+    @ClientEndpoint(decoders={MsgStringDecoder.class, MsgByteDecoder.class},
+            encoders={MsgStringEncoder.class, MsgByteEncoder.class})
+    public static class Client {
+        private Queue<Object> received = new ConcurrentLinkedQueue<>();
+
+        @OnMessage
+        public void rx(MsgString in) {
+            received.add(in);
+        }
+
+        @OnMessage
+        public void  rx(MsgByte in) {
+            received.add(in);
+        }
+    }
+
+
+    @ServerEndpoint(value="/",
+            decoders={MsgStringDecoder.class, MsgByteDecoder.class},
+            encoders={MsgStringEncoder.class, MsgByteEncoder.class},
+            configurator=ServerConfigurator.class)
+    public static class Server {
+        private Queue<Object> received = new ConcurrentLinkedQueue<>();
+
+        public Server() {
+            System.out.println("Server created");
+        }
+
+        @OnMessage
+        public MsgString rx(MsgString in) {
+            received.add(in);
+            // Echo the message back
+            return in;
+        }
+
+        @OnMessage
+        public MsgByte rx(MsgByte in) {
+            received.add(in);
+            // Echo the message back
+            return in;
+        }
+    }
+
+
+    public static class ServerConfigurator extends Configurator {
+
+        private static final Server server = new Server();
+
+        @Override
+        public <T> T getEndpointInstance(Class<T> clazz)
+                throws InstantiationException {
+            @SuppressWarnings("unchecked")
+            T result = (T) server;
+            return result;
+        }
+
+        public static Server getServerInstance() {
+            return server;
+        }
+    }
+
+    public static class ServerConfigListener extends WsListener {
+
+        @Override
+        public void contextInitialized(ServletContextEvent sce) {
+            super.contextInitialized(sce);
+            WsServerContainer sc = WsServerContainer.getServerContainer();
+            sc.setServletContext(sce.getServletContext());
+            try {
+                sc.addEndpoint(Server.class);
+            } catch (DeploymentException e) {
+                throw new IllegalStateException(e);
+            }
+        }
+    }
+
+    public static class MsgString {
+        private String data;
+
+        public String getData() { return data; }
+        public void setData(String data) { this.data = data; }
+    }
+
+
+    public static class MsgStringEncoder extends Encoder.Adapter
+            implements Encoder.Text<MsgString> {
+
+        @Override
+        public String encode(MsgString msg) throws EncodeException {
+            return "MsgString:" + msg.getData();
+        }
+    }
+
+
+    public static class MsgStringDecoder extends Decoder.Adapter
+            implements Decoder.Text<MsgString> {
+
+        @Override
+        public MsgString decode(String s) throws DecodeException {
+            MsgString result = new MsgString();
+            result.setData(s.substring(10));
+            return result;
+        }
+
+        @Override
+        public boolean willDecode(String s) {
+            return s.startsWith("MsgString:");
+        }
+    }
+
+
+    public static class MsgByte {
+        private byte[] data;
+
+        public byte[] getData() { return data; }
+        public void setData(byte[] data) { this.data = data; }
+    }
+
+
+    public static class MsgByteEncoder extends Encoder.Adapter
+            implements Encoder.Binary<MsgByte> {
+
+        @Override
+        public ByteBuffer encode(MsgByte msg) throws EncodeException {
+            byte[] data = msg.getData();
+            ByteBuffer reply = ByteBuffer.allocate(2 + data.length);
+            reply.put((byte) 0x12);
+            reply.put((byte) 0x34);
+            reply.put(data);
+            return reply;
+        }
+    }
+
+
+    public static class MsgByteDecoder extends Decoder.Adapter
+            implements Decoder.Binary<MsgByte> {
+
+        @Override
+        public MsgByte decode(ByteBuffer bb) throws DecodeException {
+            MsgByte result = new MsgByte();
+            bb.position(bb.position() + 2);
+            byte[] data = new byte[bb.limit() - bb.position()];
+            bb.get(data);
+            result.setData(data);
+            return result;
+        }
+
+        @Override
+        public boolean willDecode(ByteBuffer bb) {
+            bb.mark();
+            if (bb.get() == 0x12 && bb.get() == 0x34) {
+                return true;
+            }
+            bb.reset();
+            return false;
+        }
+    }
+}

Propchange: 
tomcat/trunk/test/org/apache/tomcat/websocket/pojo/TestEncodingDecoding.java
------------------------------------------------------------------------------
    svn:eol-style = native



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to