BoundSingleParameter(final Method method, final Class<?> type, final boolean optional) { this.type = type; int pos = -1; for (int i = 0; i < method.getParameterTypes().length; ++i) { boolean pathParam = false; for (Annotation annotation : method.getParameterAnnotations()[i]) { if (annotation.annotationType().equals(PathParam.class)) { pathParam = true; break; } } if (pathParam) { continue; } if (method.getParameterTypes()[i].equals(type)) { if (pos != -1) { throw JsrWebSocketMessages.MESSAGES.moreThanOneParameterOfType(type, method); } pos = i; } } if (pos != -1) { position = pos; } else if (optional) { position = -1; } else { throw JsrWebSocketMessages.MESSAGES.parameterNotFound(type, method); } }
BoundPathParameters( final String[] positions, final Method method, Class<?> endpointClass, Set<String> paths) throws DeploymentException { this.positions = positions; this.endpointClass = endpointClass; this.paths = paths; this.encoders = new Encoding[positions.length]; this.types = new Class[positions.length]; for (int i = 0; i < positions.length; ++i) { Class type = method.getParameterTypes()[i]; Annotation[] annotations = method.getParameterAnnotations()[i]; for (int j = 0; j < annotations.length; ++j) { if (annotations[j] instanceof PathParam) { PathParam param = (PathParam) annotations[j]; if (!paths.contains(param.value())) { JsrWebSocketLogger.ROOT_LOGGER.pathTemplateNotFound( endpointClass, param, method, paths); } } } if (positions[i] == null || type == null || type == String.class) { continue; } if (EncodingFactory.DEFAULT.canEncodeText(type)) { encoders[i] = EncodingFactory.DEFAULT.createEncoding(EmptyEndpointConfig.INSTANCE); types[i] = type; } else { throw JsrWebSocketMessages.MESSAGES.couldNotFindDecoderForType(type, method); } } }
public AnnotatedEndpoint createInstance(InstanceHandle<?> endpointInstance) { if (!endpointClass.isInstance(endpointInstance.getInstance())) { throw JsrWebSocketMessages.MESSAGES.endpointNotOfCorrectType(endpointInstance, endpointClass); } return new AnnotatedEndpoint( endpointInstance, OnOpen, OnClose, OnError, textMessage, binaryMessage, pongMessage); }
public static AnnotatedEndpointFactory create( final Class<?> endpointClass, final EncodingFactory encodingFactory, final Set<String> paths) throws DeploymentException { final Set<Class<? extends Annotation>> found = new HashSet<>(); BoundMethod onOpen = null; BoundMethod onClose = null; BoundMethod onError = null; BoundMethod textMessage = null; BoundMethod binaryMessage = null; BoundMethod pongMessage = null; Class<?> c = endpointClass; do { for (final Method method : c.getDeclaredMethods()) { if (method.isAnnotationPresent(OnOpen.class)) { if (found.contains(OnOpen.class)) { if (!onOpen.overrides(method)) { throw JsrWebSocketMessages.MESSAGES.moreThanOneAnnotation(OnOpen.class); } else { continue; } } found.add(OnOpen.class); onOpen = new BoundMethod( method, null, false, 0, new BoundSingleParameter(method, Session.class, true), new BoundSingleParameter(method, EndpointConfig.class, true), createBoundPathParameters(method, paths, endpointClass)); } if (method.isAnnotationPresent(OnClose.class)) { if (found.contains(OnClose.class)) { if (!onClose.overrides(method)) { throw JsrWebSocketMessages.MESSAGES.moreThanOneAnnotation(OnClose.class); } else { continue; } } found.add(OnClose.class); onClose = new BoundMethod( method, null, false, 0, new BoundSingleParameter(method, Session.class, true), new BoundSingleParameter(method, CloseReason.class, true), createBoundPathParameters(method, paths, endpointClass)); } if (method.isAnnotationPresent(OnError.class)) { if (found.contains(OnError.class)) { if (!onError.overrides(method)) { throw JsrWebSocketMessages.MESSAGES.moreThanOneAnnotation(OnError.class); } else { continue; } } found.add(OnError.class); onError = new BoundMethod( method, null, false, 0, new BoundSingleParameter(method, Session.class, true), new BoundSingleParameter(method, Throwable.class, false), createBoundPathParameters(method, paths, endpointClass)); } if (method.isAnnotationPresent(OnMessage.class) && !method.isBridge()) { if (binaryMessage != null && binaryMessage.overrides(method)) { continue; } if (textMessage != null && textMessage.overrides(method)) { continue; } if (pongMessage != null && pongMessage.overrides(method)) { continue; } long maxMessageSize = method.getAnnotation(OnMessage.class).maxMessageSize(); boolean messageHandled = false; // this is a bit more complex Class<?>[] parameterTypes = method.getParameterTypes(); int booleanLocation = -1; for (int i = 0; i < parameterTypes.length; ++i) { if (hasAnnotation(PathParam.class, method.getParameterAnnotations()[i])) { continue; } final Class<?> param = parameterTypes[i]; if (param == boolean.class || param == Boolean.class) { booleanLocation = i; } else if (encodingFactory.canDecodeText(param)) { if (textMessage != null) { throw JsrWebSocketMessages.MESSAGES.moreThanOneAnnotation(OnMessage.class); } textMessage = new BoundMethod( method, param, true, maxMessageSize, new BoundSingleParameter(method, Session.class, true), new BoundSingleParameter(method, boolean.class, true), new BoundSingleParameter(i, param), createBoundPathParameters(method, paths, endpointClass)); messageHandled = true; break; } else if (encodingFactory.canDecodeBinary(param)) { if (binaryMessage != null) { throw JsrWebSocketMessages.MESSAGES.moreThanOneAnnotation(OnMessage.class); } binaryMessage = new BoundMethod( method, param, true, maxMessageSize, new BoundSingleParameter(method, Session.class, true), new BoundSingleParameter(method, boolean.class, true), new BoundSingleParameter(i, param), createBoundPathParameters(method, paths, endpointClass)); messageHandled = true; break; } else if (param.equals(byte[].class)) { if (binaryMessage != null) { throw JsrWebSocketMessages.MESSAGES.moreThanOneAnnotation(OnMessage.class); } binaryMessage = new BoundMethod( method, byte[].class, false, maxMessageSize, new BoundSingleParameter(method, Session.class, true), new BoundSingleParameter(method, boolean.class, true), new BoundSingleParameter(i, byte[].class), createBoundPathParameters(method, paths, endpointClass)); messageHandled = true; break; } else if (param.equals(ByteBuffer.class)) { if (binaryMessage != null) { throw JsrWebSocketMessages.MESSAGES.moreThanOneAnnotation(OnMessage.class); } binaryMessage = new BoundMethod( method, ByteBuffer.class, false, maxMessageSize, new BoundSingleParameter(method, Session.class, true), new BoundSingleParameter(method, boolean.class, true), new BoundSingleParameter(i, ByteBuffer.class), createBoundPathParameters(method, paths, endpointClass)); messageHandled = true; break; } else if (param.equals(InputStream.class)) { if (binaryMessage != null) { throw JsrWebSocketMessages.MESSAGES.moreThanOneAnnotation(OnMessage.class); } binaryMessage = new BoundMethod( method, InputStream.class, false, maxMessageSize, new BoundSingleParameter(method, Session.class, true), new BoundSingleParameter(method, boolean.class, true), new BoundSingleParameter(i, InputStream.class), createBoundPathParameters(method, paths, endpointClass)); messageHandled = true; break; } else if (param.equals(String.class) && getPathParam(method, i) == null) { if (textMessage != null) { throw JsrWebSocketMessages.MESSAGES.moreThanOneAnnotation(OnMessage.class); } textMessage = new BoundMethod( method, String.class, false, maxMessageSize, new BoundSingleParameter(method, Session.class, true), new BoundSingleParameter(method, boolean.class, true), new BoundSingleParameter(i, String.class), createBoundPathParameters(method, paths, endpointClass)); messageHandled = true; break; } else if (param.equals(Reader.class) && getPathParam(method, i) == null) { if (textMessage != null) { throw JsrWebSocketMessages.MESSAGES.moreThanOneAnnotation(OnMessage.class); } textMessage = new BoundMethod( method, Reader.class, false, maxMessageSize, new BoundSingleParameter(method, Session.class, true), new BoundSingleParameter(method, boolean.class, true), new BoundSingleParameter(i, Reader.class), createBoundPathParameters(method, paths, endpointClass)); messageHandled = true; break; } else if (param.equals(PongMessage.class)) { if (pongMessage != null) { throw JsrWebSocketMessages.MESSAGES.moreThanOneAnnotation(OnMessage.class); } pongMessage = new BoundMethod( method, PongMessage.class, false, maxMessageSize, new BoundSingleParameter(method, Session.class, true), new BoundSingleParameter(i, PongMessage.class), createBoundPathParameters(method, paths, endpointClass)); messageHandled = true; break; } } if (!messageHandled && booleanLocation != -1) { // so it turns out that the boolean was the message type and not a final fragement // indicator if (textMessage != null) { throw JsrWebSocketMessages.MESSAGES.moreThanOneAnnotation(OnMessage.class); } Class<?> boolClass = parameterTypes[booleanLocation]; textMessage = new BoundMethod( method, boolClass, true, maxMessageSize, new BoundSingleParameter(method, Session.class, true), new BoundSingleParameter(method, boolean.class, true), new BoundSingleParameter(booleanLocation, boolClass), createBoundPathParameters(method, paths, endpointClass)); messageHandled = true; } if (!messageHandled) { throw JsrWebSocketMessages.MESSAGES.couldNotFindMessageParameter(method); } } } c = c.getSuperclass(); } while (c != Object.class && c != null); return new AnnotatedEndpointFactory( endpointClass, onOpen, onClose, onError, textMessage, binaryMessage, pongMessage); }