Author: markt
Date: Sun Dec  2 21:01:52 2012
New Revision: 1416258

URL: http://svn.apache.org/viewvc?rev=1416258&view=rev
Log:
WebSocket 1.0 implementation part 7 of many
Complete path parameter passing for POJOs

Added:
    tomcat/trunk/java/org/apache/tomcat/websocket/PathParam.java   (with props)
Modified:
    tomcat/trunk/java/javax/websocket/WebSocketPathParam.java
    tomcat/trunk/java/org/apache/tomcat/websocket/PojoMethodMapping.java
    tomcat/trunk/java/org/apache/tomcat/websocket/UriTemplate.java
    tomcat/trunk/java/org/apache/tomcat/websocket/WsEndpointPojo.java
    
tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/echo/EchoAnnotation.java
    tomcat/trunk/webapps/examples/websocket/echo.html

Modified: tomcat/trunk/java/javax/websocket/WebSocketPathParam.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/javax/websocket/WebSocketPathParam.java?rev=1416258&r1=1416257&r2=1416258&view=diff
==============================================================================
--- tomcat/trunk/java/javax/websocket/WebSocketPathParam.java (original)
+++ tomcat/trunk/java/javax/websocket/WebSocketPathParam.java Sun Dec  2 
21:01:52 2012
@@ -22,7 +22,7 @@ import java.lang.annotation.RetentionPol
 import java.lang.annotation.Target;
 
 @Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.METHOD)
+@Target(ElementType.PARAMETER)
 public @interface WebSocketPathParam {
     public String value();
 }

Added: tomcat/trunk/java/org/apache/tomcat/websocket/PathParam.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/PathParam.java?rev=1416258&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/PathParam.java (added)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/PathParam.java Sun Dec  2 
21:01:52 2012
@@ -0,0 +1,35 @@
+/*
+ *  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;
+
+public class PathParam {
+    private final Class<?> type;
+    private final String name;
+
+    public PathParam(Class<?> type, String name) {
+        this.type = type;
+        this.name = name;
+    }
+
+    public Class<?> getType() {
+        return type;
+    }
+
+    public String getName() {
+        return name;
+    }
+}

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

Modified: tomcat/trunk/java/org/apache/tomcat/websocket/PojoMethodMapping.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/PojoMethodMapping.java?rev=1416258&r1=1416257&r2=1416258&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/PojoMethodMapping.java 
(original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/PojoMethodMapping.java Sun 
Dec  2 21:01:52 2012
@@ -16,17 +16,24 @@
  */
 package org.apache.tomcat.websocket;
 
+import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
+import java.util.Map;
 
+import javax.websocket.Session;
 import javax.websocket.WebSocketClose;
 import javax.websocket.WebSocketError;
 import javax.websocket.WebSocketOpen;
+import javax.websocket.WebSocketPathParam;
 
 public class PojoMethodMapping {
 
     private final Method onOpen;
     private final Method onClose;
     private final Method onError;
+    private final PathParam[] onOpenParams;
+    private final PathParam[] onCloseParams;
+    private final PathParam[] onErrorParams;
 
     private final UriTemplate template;
 
@@ -54,36 +61,139 @@ public class PojoMethodMapping {
 
         if (path.length() > mappingPath.length()) {
             template =
-                    new UriTemplate(path.substring(mappingPath.length() - 1));
+                    new UriTemplate(path.substring(mappingPath.length() - 2));
         } else {
             template = null;
         }
+
+        onOpenParams = getPathParams(onOpen, false);
+        onCloseParams = getPathParams(onClose, false);
+        onErrorParams = getPathParams(onError, true);
     }
 
+
     public Method getOnOpen() {
         return onOpen;
     }
 
-    public Object[] getOnOpenArgs(String pathInfo) {
-        // TODO Auto-generated method stub
-        return null;
+
+    public Object[] getOnOpenArgs(String pathInfo, Session session) {
+        return buildArgs(onOpenParams, template, pathInfo, session, null);
     }
 
+
     public Method getOnClose() {
         return onClose;
     }
 
-    public Object[] getOnCloseArgs(String pathInfo) {
-        // TODO Auto-generated method stub
-        return null;
+
+    public Object[] getOnCloseArgs(String pathInfo, Session session) {
+        return buildArgs(onCloseParams, template, pathInfo, session, null);
     }
 
     public Method getOnError() {
         return onError;
     }
 
-    public Object[] getOnErrorArgs(String pathInfo) {
-        // TODO Auto-generated method stub
-        return null;
+
+    public Object[] getOnErrorArgs(String pathInfo, Session session,
+            Throwable throwable) {
+        return buildArgs(onErrorParams, template, pathInfo, session, 
throwable);
+    }
+
+
+    private static PathParam[] getPathParams(Method m, boolean isError) {
+        if (m == null) {
+            return new PathParam[0];
+        }
+
+        boolean foundError = !isError;
+        Class<?>[] types = m.getParameterTypes();
+        Annotation[][] paramsAnnotations = m.getParameterAnnotations();
+        PathParam[] result = new PathParam[types.length];
+
+        for (int i = 0; i < types.length; i++) {
+            Class<?> type = types[i];
+            if (type.equals(Session.class)) {
+                result[i] = new PathParam(type, null);
+            } else if (type.equals(Throwable.class)) {
+                foundError = true;
+                result[i] = new PathParam(type, null);
+            } else {
+                Annotation[] paramAnnotations = paramsAnnotations[i];
+                for (Annotation paramAnnotation : paramAnnotations) {
+                    if (paramAnnotation.annotationType().equals(
+                            WebSocketPathParam.class)) {
+                        result[i] = new PathParam(type,
+                                ((WebSocketPathParam) 
paramAnnotation).value());
+                        break;
+                    }
+                }
+                // Parameters without annotations are not permitted
+                if (result[i] == null) {
+                    throw new IllegalArgumentException();
+                }
+            }
+        }
+
+        if (!foundError) {
+            throw new IllegalArgumentException();
+        }
+
+        return result;
+    }
+
+
+    private static Object[] buildArgs(PathParam[] pathParams,
+            UriTemplate template, String pathInfo, Session session,
+            Throwable throwable) {
+        Object[] result = new Object[pathParams.length];
+        Map<String, String> pathValues = template.match(pathInfo);
+
+        for (int i = 0; i < pathParams.length; i++) {
+            Class<?> type = pathParams[i].getType();
+            if (type.equals(Session.class)) {
+                result[i] = session;
+            } else if (type.equals(Throwable.class)) {
+                result[i] = throwable;
+            } else {
+                String name = pathParams[i].getName();
+                String value = pathValues.get(name);
+                if (value == null) {
+                    result[i] = null;
+                } else {
+                    result[i] = coerceToType(type, value);
+                }
+            }
+        }
+        return result;
+    }
+
+
+    private static Object coerceToType(Class<?> type, String value) {
+
+        if (type.equals(String.class)) {
+            return value;
+        } else if (type.equals(boolean.class) || type.equals(Boolean.class)) {
+            return Boolean.valueOf(value);
+        } else if (type.equals(byte.class) || type.equals(Byte.class)) {
+            return Byte.valueOf(value);
+        } else if (value.length() == 1 &&
+                type.equals(char.class) || type.equals(Character.class)) {
+            return Character.valueOf(value.charAt(0));
+        } else if (type.equals(double.class) || type.equals(Double.class)) {
+            return Double.valueOf(value);
+        } else if (type.equals(float.class) || type.equals(Float.class)) {
+            return Float.valueOf(value);
+        } else if (type.equals(int.class) || type.equals(Integer.class)) {
+            return Integer.valueOf(value);
+        } else if (type.equals(long.class) || type.equals(Long.class)) {
+            return Long.valueOf(value);
+        } else if (type.equals(short.class) || type.equals(Short.class)) {
+            return Short.valueOf(value);
+        } else {
+            // TODO
+            throw new IllegalArgumentException();
+        }
     }
 }

Modified: tomcat/trunk/java/org/apache/tomcat/websocket/UriTemplate.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/UriTemplate.java?rev=1416258&r1=1416257&r2=1416258&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/UriTemplate.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/UriTemplate.java Sun Dec  2 
21:01:52 2012
@@ -57,6 +57,11 @@ public class UriTemplate {
     }
 
 
+    public boolean contains(String name) {
+        return names.contains(name);
+    }
+
+
     /**
      * Extract the path parameters from the provided pathInfo based on the
      * template with which this UriTemplate was constructed.

Modified: tomcat/trunk/java/org/apache/tomcat/websocket/WsEndpointPojo.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/WsEndpointPojo.java?rev=1416258&r1=1416257&r2=1416258&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/WsEndpointPojo.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/WsEndpointPojo.java Sun Dec  
2 21:01:52 2012
@@ -17,7 +17,6 @@
 package org.apache.tomcat.websocket;
 
 import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
 
 import javax.websocket.CloseReason;
 import javax.websocket.DefaultServerConfiguration;
@@ -29,12 +28,9 @@ public class WsEndpointPojo extends Endp
 
     private final Object pojo;
     private final EndpointConfiguration config;
-    private final Method onOpen;
-    private final Object[] onOpenArgs;
-    private final Method onClose;
-    private final Object[] onCloseArgs;
-    private final Method onError;
-    private final Object[] onErrorArgs;
+    private final String pathInfo;
+    private final PojoMethodMapping methodMapping;
+    private Session session = null;
 
     public WsEndpointPojo(Class<?> clazzPojo, PojoMethodMapping methodMapping,
             String ServletPath, String pathInfo)
@@ -48,26 +44,8 @@ public class WsEndpointPojo extends Endp
             }
         };
 
-        onOpen = methodMapping.getOnOpen();
-        if (onOpen == null) {
-            onOpenArgs = null;
-        } else {
-            onOpenArgs = methodMapping.getOnOpenArgs(pathInfo);
-        }
-
-        onClose = methodMapping.getOnClose();
-        if (onClose == null) {
-            onCloseArgs = null;
-        } else {
-            onCloseArgs = methodMapping.getOnCloseArgs(pathInfo);
-        }
-
-        onError = methodMapping.getOnError();
-        if (onError == null) {
-            onErrorArgs = null;
-        } else {
-            onErrorArgs = methodMapping.getOnErrorArgs(pathInfo);
-        }
+        this.methodMapping = methodMapping;
+        this.pathInfo = pathInfo;
     }
 
     @Override
@@ -77,10 +55,12 @@ public class WsEndpointPojo extends Endp
 
     @Override
     public void onOpen(Session session) {
-        // TODO Insert the session into the method args
-        if (onOpen != null) {
+        this.session = session;
+
+        if (methodMapping.getOnOpen() != null) {
             try {
-                onOpen.invoke(pojo, onOpenArgs);
+                methodMapping.getOnOpen().invoke(
+                        pojo, methodMapping.getOnOpenArgs(pathInfo, session));
             } catch (IllegalAccessException | IllegalArgumentException
                     | InvocationTargetException e) {
                 // TODO Auto-generated catch block
@@ -91,9 +71,10 @@ public class WsEndpointPojo extends Endp
 
     @Override
     public void onClose(CloseReason closeReason) {
-        if (onClose != null) {
+        if (methodMapping.getOnClose() != null) {
             try {
-                onClose.invoke(pojo, onCloseArgs);
+                methodMapping.getOnClose().invoke(
+                        pojo, methodMapping.getOnCloseArgs(pathInfo, session));
             } catch (IllegalAccessException | IllegalArgumentException
                     | InvocationTargetException e) {
                 // TODO Auto-generated catch block
@@ -104,10 +85,11 @@ public class WsEndpointPojo extends Endp
 
     @Override
     public void onError(Throwable throwable) {
-        if (onError != null) {
+        if (methodMapping.getOnError() != null) {
             try {
-                // TODO Insert throwable
-                onError.invoke(pojo, onErrorArgs);
+                methodMapping.getOnError().invoke(pojo,
+                        methodMapping.getOnErrorArgs(
+                                pathInfo, session, throwable));
             } catch (IllegalAccessException | IllegalArgumentException
                     | InvocationTargetException e) {
                 // TODO Auto-generated catch block

Modified: 
tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/echo/EchoAnnotation.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/echo/EchoAnnotation.java?rev=1416258&r1=1416257&r2=1416258&view=diff
==============================================================================
--- 
tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/echo/EchoAnnotation.java
 (original)
+++ 
tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/echo/EchoAnnotation.java
 Sun Dec  2 21:01:52 2012
@@ -18,12 +18,13 @@ package websocket.echo;
 
 import javax.websocket.WebSocketEndpoint;
 import javax.websocket.WebSocketOpen;
+import javax.websocket.WebSocketPathParam;
 
-@WebSocketEndpoint("/websocket/echoAnnotation")
+@WebSocketEndpoint("/websocket/echoAnnotation/{test}")
 public class EchoAnnotation {
 
     @WebSocketOpen
-    public void printOpen() {
-        System.out.println("EchoAnnotation.printOpen()");
+    public void printOpen(@WebSocketPathParam("test") String test) {
+        System.out.println("EchoAnnotation.printOpen() with [" + test + "]");
     }
 }

Modified: tomcat/trunk/webapps/examples/websocket/echo.html
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/webapps/examples/websocket/echo.html?rev=1416258&r1=1416257&r2=1416258&view=diff
==============================================================================
--- tomcat/trunk/webapps/examples/websocket/echo.html (original)
+++ tomcat/trunk/webapps/examples/websocket/echo.html Sun Dec  2 21:01:52 2012
@@ -141,7 +141,7 @@
             <input id="radio3" type="radio" name="group1" 
value="/examples/websocket/echoProgrammatic"
                    onclick="updateTarget(this.value);"> <label 
for="radio2">new programmatic</label>
             <!-- echo example using new annotation API on the server side -->
-            <input id="radio3" type="radio" name="group1" 
value="/examples/websocket/echoAnnotation"
+            <input id="radio4" type="radio" name="group1" 
value="/examples/websocket/echoAnnotation/HelloWorld"
                    onclick="updateTarget(this.value);"> <label 
for="radio2">new annotation</label>
         </div>
         <div>



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

Reply via email to