Browse Source

AnnotationScanner improvements

master
Nikita 11 years ago
parent
commit
0e982a3281
  1. 2
      src/main/java/com/corundumstudio/socketio/annotation/AnnotationScanner.java
  2. 2
      src/main/java/com/corundumstudio/socketio/annotation/OnConnectScanner.java
  3. 7
      src/main/java/com/corundumstudio/socketio/annotation/OnDisconnectScanner.java
  4. 4
      src/main/java/com/corundumstudio/socketio/annotation/OnEventScanner.java
  5. 2
      src/main/java/com/corundumstudio/socketio/annotation/OnJsonObjectScanner.java
  6. 2
      src/main/java/com/corundumstudio/socketio/annotation/OnMessageScanner.java
  7. 71
      src/main/java/com/corundumstudio/socketio/annotation/ScannerEngine.java
  8. 5
      src/main/java/com/corundumstudio/socketio/namespace/Namespace.java

2
src/main/java/com/corundumstudio/socketio/annotation/AnnotationScanner.java

@ -24,7 +24,7 @@ public interface AnnotationScanner {
Class<? extends Annotation> 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);

2
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) {

7
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<? extends Annotation> 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) {

4
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");
}

2
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);

2
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);

71
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<? extends AnnotationScanner> 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) {

5
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<UUID, SocketIOClient> allClients = new ConcurrentHashMap<UUID, SocketIOClient>();
private final ConcurrentMap<String, EventEntry<?>> eventListeners =
new ConcurrentHashMap<String, EventEntry<?>>();
@ -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);
}

Loading…
Cancel
Save