001/* 002 * Copyright 2002-2015 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.web.bind.annotation.support; 018 019import java.lang.reflect.Method; 020import java.lang.reflect.Proxy; 021import java.util.Arrays; 022import java.util.Collections; 023import java.util.HashSet; 024import java.util.LinkedHashSet; 025import java.util.Set; 026import java.util.concurrent.ConcurrentHashMap; 027 028import org.springframework.core.BridgeMethodResolver; 029import org.springframework.core.annotation.AnnotationUtils; 030import org.springframework.util.ClassUtils; 031import org.springframework.util.ReflectionUtils; 032import org.springframework.web.bind.annotation.InitBinder; 033import org.springframework.web.bind.annotation.ModelAttribute; 034import org.springframework.web.bind.annotation.RequestMapping; 035import org.springframework.web.bind.annotation.SessionAttributes; 036 037/** 038 * Support class for resolving web method annotations in a handler type. 039 * Processes {@code @RequestMapping}, {@code @InitBinder}, 040 * {@code @ModelAttribute} and {@code @SessionAttributes}. 041 * 042 * <p>Used by {@link org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter} 043 * and {@link org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter}. 044 * 045 * @author Juergen Hoeller 046 * @since 2.5.2 047 * @see org.springframework.web.bind.annotation.RequestMapping 048 * @see org.springframework.web.bind.annotation.InitBinder 049 * @see org.springframework.web.bind.annotation.ModelAttribute 050 * @see org.springframework.web.bind.annotation.SessionAttributes 051 * @deprecated as of 4.3, in favor of the {@code HandlerMethod}-based MVC infrastructure 052 */ 053@Deprecated 054public class HandlerMethodResolver { 055 056 private final Set<Method> handlerMethods = new LinkedHashSet<Method>(); 057 058 private final Set<Method> initBinderMethods = new LinkedHashSet<Method>(); 059 060 private final Set<Method> modelAttributeMethods = new LinkedHashSet<Method>(); 061 062 private RequestMapping typeLevelMapping; 063 064 private boolean sessionAttributesFound; 065 066 private final Set<String> sessionAttributeNames = new HashSet<String>(); 067 068 private final Set<Class<?>> sessionAttributeTypes = new HashSet<Class<?>>(); 069 070 private final Set<String> actualSessionAttributeNames = 071 Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(4)); 072 073 074 /** 075 * Initialize a new HandlerMethodResolver for the specified handler type. 076 * @param handlerType the handler class to introspect 077 */ 078 public void init(final Class<?> handlerType) { 079 Set<Class<?>> handlerTypes = new LinkedHashSet<Class<?>>(); 080 Class<?> specificHandlerType = null; 081 if (!Proxy.isProxyClass(handlerType)) { 082 handlerTypes.add(handlerType); 083 specificHandlerType = handlerType; 084 } 085 handlerTypes.addAll(Arrays.asList(handlerType.getInterfaces())); 086 for (Class<?> currentHandlerType : handlerTypes) { 087 final Class<?> targetClass = (specificHandlerType != null ? specificHandlerType : currentHandlerType); 088 ReflectionUtils.doWithMethods(currentHandlerType, new ReflectionUtils.MethodCallback() { 089 @Override 090 public void doWith(Method method) { 091 Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass); 092 Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(specificMethod); 093 if (isHandlerMethod(specificMethod) && 094 (bridgedMethod == specificMethod || !isHandlerMethod(bridgedMethod))) { 095 handlerMethods.add(specificMethod); 096 } 097 else if (isInitBinderMethod(specificMethod) && 098 (bridgedMethod == specificMethod || !isInitBinderMethod(bridgedMethod))) { 099 initBinderMethods.add(specificMethod); 100 } 101 else if (isModelAttributeMethod(specificMethod) && 102 (bridgedMethod == specificMethod || !isModelAttributeMethod(bridgedMethod))) { 103 modelAttributeMethods.add(specificMethod); 104 } 105 } 106 }, ReflectionUtils.USER_DECLARED_METHODS); 107 } 108 this.typeLevelMapping = AnnotationUtils.findAnnotation(handlerType, RequestMapping.class); 109 SessionAttributes sessionAttributes = AnnotationUtils.findAnnotation(handlerType, SessionAttributes.class); 110 this.sessionAttributesFound = (sessionAttributes != null); 111 if (this.sessionAttributesFound) { 112 this.sessionAttributeNames.addAll(Arrays.asList(sessionAttributes.names())); 113 this.sessionAttributeTypes.addAll(Arrays.asList(sessionAttributes.types())); 114 } 115 } 116 117 protected boolean isHandlerMethod(Method method) { 118 return AnnotationUtils.findAnnotation(method, RequestMapping.class) != null; 119 } 120 121 protected boolean isInitBinderMethod(Method method) { 122 return AnnotationUtils.findAnnotation(method, InitBinder.class) != null; 123 } 124 125 protected boolean isModelAttributeMethod(Method method) { 126 return AnnotationUtils.findAnnotation(method, ModelAttribute.class) != null; 127 } 128 129 130 public final boolean hasHandlerMethods() { 131 return !this.handlerMethods.isEmpty(); 132 } 133 134 public final Set<Method> getHandlerMethods() { 135 return this.handlerMethods; 136 } 137 138 public final Set<Method> getInitBinderMethods() { 139 return this.initBinderMethods; 140 } 141 142 public final Set<Method> getModelAttributeMethods() { 143 return this.modelAttributeMethods; 144 } 145 146 public boolean hasTypeLevelMapping() { 147 return (this.typeLevelMapping != null); 148 } 149 150 public RequestMapping getTypeLevelMapping() { 151 return this.typeLevelMapping; 152 } 153 154 public boolean hasSessionAttributes() { 155 return this.sessionAttributesFound; 156 } 157 158 public boolean isSessionAttribute(String attrName, Class<?> attrType) { 159 if (this.sessionAttributeNames.contains(attrName) || this.sessionAttributeTypes.contains(attrType)) { 160 this.actualSessionAttributeNames.add(attrName); 161 return true; 162 } 163 else { 164 return false; 165 } 166 } 167 168 public Set<String> getActualSessionAttributeNames() { 169 return this.actualSessionAttributeNames; 170 } 171 172}