diff --git a/src/main/java/com/corundumstudio/socketio/annotation/AnnotationScanner.java b/src/main/java/com/corundumstudio/socketio/annotation/AnnotationScanner.java index 7b4ec17..9756841 100644 --- a/src/main/java/com/corundumstudio/socketio/annotation/AnnotationScanner.java +++ b/src/main/java/com/corundumstudio/socketio/annotation/AnnotationScanner.java @@ -24,7 +24,7 @@ public interface AnnotationScanner { Class getScanAnnotation(); - void addListener(Namespace namespace, Object object, Class clazz, Method method); + void addListener(Namespace namespace, Object object, Method method, Annotation annotation); void validate(Method method, Class clazz); diff --git a/src/main/java/com/corundumstudio/socketio/annotation/OnConnectScanner.java b/src/main/java/com/corundumstudio/socketio/annotation/OnConnectScanner.java index f1c84c7..5f9d707 100644 --- a/src/main/java/com/corundumstudio/socketio/annotation/OnConnectScanner.java +++ b/src/main/java/com/corundumstudio/socketio/annotation/OnConnectScanner.java @@ -29,7 +29,7 @@ public class OnConnectScanner implements AnnotationScanner { return OnConnect.class; } - public void addListener(Namespace namespace, final Object object, final Class clazz, final Method method) { + public void addListener(Namespace namespace, final Object object, final Method method, Annotation annotation) { namespace.addConnectListener(new ConnectListener() { @Override public void onConnect(SocketIOClient client) { diff --git a/src/main/java/com/corundumstudio/socketio/annotation/OnDisconnectScanner.java b/src/main/java/com/corundumstudio/socketio/annotation/OnDisconnectScanner.java index 5aef37c..ea2a90e 100644 --- a/src/main/java/com/corundumstudio/socketio/annotation/OnDisconnectScanner.java +++ b/src/main/java/com/corundumstudio/socketio/annotation/OnDisconnectScanner.java @@ -18,9 +18,6 @@ package com.corundumstudio.socketio.annotation; import java.lang.annotation.Annotation; import java.lang.reflect.Method; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.corundumstudio.socketio.SocketIOClient; import com.corundumstudio.socketio.handler.SocketIOException; import com.corundumstudio.socketio.listener.DisconnectListener; @@ -28,15 +25,13 @@ import com.corundumstudio.socketio.namespace.Namespace; public class OnDisconnectScanner implements AnnotationScanner { - private final Logger log = LoggerFactory.getLogger(getClass()); - @Override public Class getScanAnnotation() { return OnDisconnect.class; } @Override - public void addListener(Namespace namespace, final Object object, final Class clazz, final Method method) { + public void addListener(Namespace namespace, final Object object, final Method method, Annotation annotation) { namespace.addDisconnectListener(new DisconnectListener() { @Override public void onDisconnect(SocketIOClient client) { diff --git a/src/main/java/com/corundumstudio/socketio/annotation/OnEventScanner.java b/src/main/java/com/corundumstudio/socketio/annotation/OnEventScanner.java index 45f86fa..9f845e4 100644 --- a/src/main/java/com/corundumstudio/socketio/annotation/OnEventScanner.java +++ b/src/main/java/com/corundumstudio/socketio/annotation/OnEventScanner.java @@ -37,8 +37,8 @@ public class OnEventScanner implements AnnotationScanner { @Override @SuppressWarnings("unchecked") - public void addListener(Namespace namespace, final Object object, final Class clazz, final Method method) { - OnEvent annotation = method.getAnnotation(OnEvent.class); + public void addListener(Namespace namespace, final Object object, final Method method, Annotation annot) { + OnEvent annotation = (OnEvent) annot; if (annotation.value() == null || annotation.value().trim().length() == 0) { throw new IllegalArgumentException("OnEvent \"value\" parameter is required"); } diff --git a/src/main/java/com/corundumstudio/socketio/annotation/OnJsonObjectScanner.java b/src/main/java/com/corundumstudio/socketio/annotation/OnJsonObjectScanner.java index 88d0a3d..3497241 100644 --- a/src/main/java/com/corundumstudio/socketio/annotation/OnJsonObjectScanner.java +++ b/src/main/java/com/corundumstudio/socketio/annotation/OnJsonObjectScanner.java @@ -33,7 +33,7 @@ public class OnJsonObjectScanner implements AnnotationScanner { @Override @SuppressWarnings("unchecked") - public void addListener(Namespace namespace, final Object object, final Class clazz, final Method method) { + public void addListener(Namespace namespace, final Object object, final Method method, Annotation annot) { final int socketIOClientIndex = paramIndex(method, SocketIOClient.class); final int ackRequestIndex = paramIndex(method, AckRequest.class); final int dataIndex = dataIndex(method); diff --git a/src/main/java/com/corundumstudio/socketio/annotation/OnMessageScanner.java b/src/main/java/com/corundumstudio/socketio/annotation/OnMessageScanner.java index 52be25c..3a35f96 100644 --- a/src/main/java/com/corundumstudio/socketio/annotation/OnMessageScanner.java +++ b/src/main/java/com/corundumstudio/socketio/annotation/OnMessageScanner.java @@ -32,7 +32,7 @@ public class OnMessageScanner implements AnnotationScanner { } @Override - public void addListener(Namespace namespace, final Object object, final Class clazz, final Method method) { + public void addListener(Namespace namespace, final Object object, final Method method, Annotation annot) { final int socketIOClientIndex = paramIndex(method, SocketIOClient.class); final int ackRequestIndex = paramIndex(method, AckRequest.class); final int dataIndex = paramIndex(method, String.class); diff --git a/src/main/java/com/corundumstudio/socketio/annotation/ScannerEngine.java b/src/main/java/com/corundumstudio/socketio/annotation/ScannerEngine.java index 840129e..b2ffde8 100644 --- a/src/main/java/com/corundumstudio/socketio/annotation/ScannerEngine.java +++ b/src/main/java/com/corundumstudio/socketio/annotation/ScannerEngine.java @@ -15,40 +15,85 @@ */ package com.corundumstudio.socketio.annotation; +import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Arrays; import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.corundumstudio.socketio.namespace.Namespace; public class ScannerEngine { + private final Logger log = LoggerFactory.getLogger(getClass()); + private static final List annotations = Arrays.asList(new OnConnectScanner(), new OnDisconnectScanner(), new OnEventScanner(), new OnJsonObjectScanner(), new OnMessageScanner()); + private Method findSimilarMethod(Class objectClazz, Method method) { + Method[] methods = objectClazz.getDeclaredMethods(); + for (Method m : methods) { + if (equals(m, method)) { + return m; + } + } + return null; + } + public void scan(Namespace namespace, Object object, Class clazz) throws IllegalArgumentException { - Method[] methods = clazz.getDeclaredMethods(); - for (Method method : methods) { - for (AnnotationScanner annotationScanner : annotations) { - if (method.isAnnotationPresent(annotationScanner.getScanAnnotation())) { - annotationScanner.validate(method, clazz); - makeAccessible(method); - annotationScanner.addListener(namespace, object, clazz, method); + + if (!clazz.isAssignableFrom(object.getClass())) { + for (Method method : methods) { + for (AnnotationScanner annotationScanner : annotations) { + Annotation ann = method.getAnnotation(annotationScanner.getScanAnnotation()); + if (ann != null) { + annotationScanner.validate(method, clazz); + + Method m = findSimilarMethod(object.getClass(), method); + if (m != null) { + annotationScanner.addListener(namespace, object, m, ann); + } else { + log.warn("Method similar to " + method.getName() + " can't be found in " + object.getClass()); + } + } + } + } + } else { + for (Method method : methods) { + for (AnnotationScanner annotationScanner : annotations) { + Annotation ann = method.getAnnotation(annotationScanner.getScanAnnotation()); + if (ann != null) { + annotationScanner.validate(method, clazz); + makeAccessible(method); + annotationScanner.addListener(namespace, object, method, ann); + } } } - } - if (clazz.getSuperclass() != null) { - scan(namespace, object, clazz.getSuperclass()); - } else if (clazz.isInterface()) { - for (Class superIfc : clazz.getInterfaces()) { - scan(namespace, object, superIfc); + if (clazz.getSuperclass() != null) { + scan(namespace, object, clazz.getSuperclass()); + } else if (clazz.isInterface()) { + for (Class superIfc : clazz.getInterfaces()) { + scan(namespace, object, superIfc); + } } } + + } + + private boolean equals(Method method1, Method method2) { + if (!method1.getName().equals(method2.getName()) + || !method1.getReturnType().equals(method2.getReturnType())) { + return false; + } + + return Arrays.equals(method1.getParameterTypes(), method2.getParameterTypes()); } private void makeAccessible(Method method) { diff --git a/src/main/java/com/corundumstudio/socketio/namespace/Namespace.java b/src/main/java/com/corundumstudio/socketio/namespace/Namespace.java index 5042313..6fa8214 100644 --- a/src/main/java/com/corundumstudio/socketio/namespace/Namespace.java +++ b/src/main/java/com/corundumstudio/socketio/namespace/Namespace.java @@ -58,6 +58,7 @@ public class Namespace implements SocketIONamespace { public static final String DEFAULT_NAME = ""; + private final ScannerEngine engine = new ScannerEngine(); private final Map allClients = new ConcurrentHashMap(); private final ConcurrentMap> eventListeners = new ConcurrentHashMap>(); @@ -249,13 +250,11 @@ public class Namespace implements SocketIONamespace { @Override public void addListeners(Object listeners) { - ScannerEngine engine = new ScannerEngine(); - engine.scan(this, listeners, listeners.getClass()); + addListeners(listeners, listeners.getClass()); } @Override public void addListeners(Object listeners, Class listenersClass) { - ScannerEngine engine = new ScannerEngine(); engine.scan(this, listeners, listenersClass); }