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: [email protected]
For additional commands, e-mail: [email protected]