revised handler method resolution, in particular with respect to generic interfaces (SPR-7355)

This commit is contained in:
Juergen Hoeller
2010-08-15 21:12:54 +00:00
parent 49a2970def
commit 35971f9f90
7 changed files with 322 additions and 114 deletions

View File

@@ -435,6 +435,9 @@ public class AnnotationMethodHandlerAdapter extends PortletContentGenerator
@Override
protected boolean isHandlerMethod(Method method) {
if (this.mappings.containsKey(method)) {
return true;
}
RequestMappingInfo mappingInfo = new RequestMappingInfo();
RequestMapping requestMapping = AnnotationUtils.findAnnotation(method, RequestMapping.class);
ActionMapping actionMapping = AnnotationUtils.findAnnotation(method, ActionMapping.class);
@@ -460,8 +463,11 @@ public class AnnotationMethodHandlerAdapter extends PortletContentGenerator
mappingInfo.phase = determineDefaultPhase(method);
}
}
this.mappings.put(method, mappingInfo);
return (mappingInfo.phase != null);
if (mappingInfo.phase != null) {
this.mappings.put(method, mappingInfo);
return true;
}
return false;
}
public Method resolveHandlerMethod(PortletRequest request) throws PortletException {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@ import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import javax.portlet.ClientDataRequest;
@@ -145,71 +146,76 @@ public class DefaultAnnotationHandlerMapping extends AbstractMapBasedHandlerMapp
* @return <code>true</code> if at least 1 handler method has been registered;
* <code>false</code> otherwise
*/
protected boolean detectHandlerMethods(Class handlerType, final String beanName, final RequestMapping typeMapping) {
protected boolean detectHandlerMethods(Class<?> handlerType, final String beanName, final RequestMapping typeMapping) {
final Set<Boolean> handlersRegistered = new HashSet<Boolean>(1);
ReflectionUtils.doWithMethods(handlerType, new ReflectionUtils.MethodCallback() {
public void doWith(Method method) {
boolean mappingFound = false;
String[] modeKeys = new String[0];
String[] params = new String[0];
String resourceId = null;
String eventName = null;
for (Annotation ann : method.getAnnotations()) {
if (AnnotationUtils.findAnnotation(ann.getClass(), Mapping.class) != null) {
mappingFound = true;
if (ann instanceof RequestMapping) {
RequestMapping rm = (RequestMapping) ann;
modeKeys = rm.value();
params = StringUtils.mergeStringArrays(params, rm.params());
}
else if (ann instanceof ResourceMapping) {
ResourceMapping rm = (ResourceMapping) ann;
resourceId = rm.value();
}
else if (ann instanceof EventMapping) {
EventMapping em = (EventMapping) ann;
eventName = em.value();
}
else {
String[] specificParams = (String[]) AnnotationUtils.getValue(ann, "params");
params = StringUtils.mergeStringArrays(params, specificParams);
Set<Class<?>> handlerTypes = new LinkedHashSet<Class<?>>();
handlerTypes.add(handlerType);
handlerTypes.addAll(Arrays.asList(handlerType.getInterfaces()));
for (Class<?> currentHandlerType : handlerTypes) {
ReflectionUtils.doWithMethods(currentHandlerType, new ReflectionUtils.MethodCallback() {
public void doWith(Method method) {
boolean mappingFound = false;
String[] modeKeys = new String[0];
String[] params = new String[0];
String resourceId = null;
String eventName = null;
for (Annotation ann : method.getAnnotations()) {
if (AnnotationUtils.findAnnotation(ann.getClass(), Mapping.class) != null) {
mappingFound = true;
if (ann instanceof RequestMapping) {
RequestMapping rm = (RequestMapping) ann;
modeKeys = rm.value();
params = StringUtils.mergeStringArrays(params, rm.params());
}
else if (ann instanceof ResourceMapping) {
ResourceMapping rm = (ResourceMapping) ann;
resourceId = rm.value();
}
else if (ann instanceof EventMapping) {
EventMapping em = (EventMapping) ann;
eventName = em.value();
}
else {
String[] specificParams = (String[]) AnnotationUtils.getValue(ann, "params");
params = StringUtils.mergeStringArrays(params, specificParams);
}
}
}
}
if (mappingFound) {
if (modeKeys.length == 0) {
if (mappingFound) {
if (modeKeys.length == 0) {
if (typeMapping != null) {
modeKeys = typeMapping.value();
}
else {
throw new IllegalStateException(
"No portlet mode mappings specified - neither at type nor at method level");
}
}
if (typeMapping != null) {
modeKeys = typeMapping.value();
if (!PortletAnnotationMappingUtils.validateModeMapping(modeKeys, typeMapping.value())) {
throw new IllegalStateException("Mode mappings conflict between method and type level: " +
Arrays.asList(modeKeys) + " versus " + Arrays.asList(typeMapping.value()));
}
params = StringUtils.mergeStringArrays(typeMapping.params(), params);
}
PortletRequestMappingPredicate predicate;
if (resourceId != null) {
predicate = new ResourceMappingPredicate(resourceId);
}
else if (eventName != null) {
predicate = new EventMappingPredicate(eventName);
}
else {
throw new IllegalStateException(
"No portlet mode mappings specified - neither at type nor at method level");
predicate = new ParameterMappingPredicate(params);
}
}
if (typeMapping != null) {
if (!PortletAnnotationMappingUtils.validateModeMapping(modeKeys, typeMapping.value())) {
throw new IllegalStateException("Mode mappings conflict between method and type level: " +
Arrays.asList(modeKeys) + " versus " + Arrays.asList(typeMapping.value()));
for (String modeKey : modeKeys) {
registerHandler(new PortletMode(modeKey), beanName, predicate);
handlersRegistered.add(Boolean.TRUE);
}
params = StringUtils.mergeStringArrays(typeMapping.params(), params);
}
PortletRequestMappingPredicate predicate;
if (resourceId != null) {
predicate = new ResourceMappingPredicate(resourceId);
}
else if (eventName != null) {
predicate = new EventMappingPredicate(eventName);
}
else {
predicate = new ParameterMappingPredicate(params);
}
for (String modeKey : modeKeys) {
registerHandler(new PortletMode(modeKey), beanName, predicate);
handlersRegistered.add(Boolean.TRUE);
}
}
}
});
}, ReflectionUtils.USER_DECLARED_METHODS);
}
return !handlersRegistered.isEmpty();
}