Source Code Cross Referenced for BridgeMethodResolver.java in  » J2EE » spring-framework-2.5 » org » springframework » core » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » J2EE » spring framework 2.5 » org.springframework.core 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2002-2007 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:         *      http://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:
017:        package org.springframework.core;
018:
019:        import java.lang.reflect.GenericArrayType;
020:        import java.lang.reflect.Method;
021:        import java.lang.reflect.ParameterizedType;
022:        import java.lang.reflect.Type;
023:        import java.lang.reflect.TypeVariable;
024:        import java.util.ArrayList;
025:        import java.util.HashMap;
026:        import java.util.List;
027:        import java.util.Map;
028:
029:        import org.springframework.util.Assert;
030:        import org.springframework.util.ClassUtils;
031:        import org.springframework.util.ReflectionUtils;
032:
033:        /**
034:         * Helper for resolving synthetic {@link Method#isBridge bridge Methods} to the
035:         * {@link Method} being bridged.
036:         *
037:         * <p>Given a synthetic {@link Method#isBridge bridge Method} returns the {@link Method}
038:         * being bridged. A bridge method may be created by the compiler when extending a
039:         * parameterized type whose methods have parameterized arguments. During runtime
040:         * invocation the bridge {@link Method} may be invoked and/or used via reflection.
041:         * When attempting to locate annotations on {@link Method Methods}, it is wise to check
042:         * for bridge {@link Method Methods} as appropriate and find the bridged {@link Method}.
043:         *
044:         * <p>See <a href="http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.12.4.5">
045:         * The Java Language Specification</a> for more details on the use of bridge methods.
046:         *
047:         * <p>Only usable on JDK 1.5 and higher. Use an appropriate {@link JdkVersion}
048:         * check before calling this class, if a fallback for JDK 1.4 is desirable.
049:         *
050:         * @author Rob Harrop
051:         * @author Juergen Hoeller
052:         * @since 2.0
053:         * @see JdkVersion
054:         */
055:        public abstract class BridgeMethodResolver {
056:
057:            /**
058:             * Find the original method for the supplied {@link Method bridge Method}.
059:             * <p>It is safe to call this method passing in a non-bridge {@link Method} instance.
060:             * In such a case, the supplied {@link Method} instance is returned directly to the caller.
061:             * Callers are <strong>not</strong> required to check for bridging before calling this method.
062:             * @throws IllegalStateException if no bridged {@link Method} can be found
063:             */
064:            public static Method findBridgedMethod(Method bridgeMethod) {
065:                Assert.notNull(bridgeMethod, "Method must not be null");
066:
067:                if (!bridgeMethod.isBridge()) {
068:                    return bridgeMethod;
069:                }
070:
071:                // Gather all methods with matching name and parameter size.
072:                List candidateMethods = new ArrayList();
073:                Method[] methods = ReflectionUtils
074:                        .getAllDeclaredMethods(bridgeMethod.getDeclaringClass());
075:                for (int i = 0; i < methods.length; i++) {
076:                    Method candidateMethod = methods[i];
077:                    if (isBridgedCandidateFor(candidateMethod, bridgeMethod)) {
078:                        candidateMethods.add(candidateMethod);
079:                    }
080:                }
081:
082:                Method result;
083:                // Now perform simple quick checks.
084:                if (candidateMethods.size() == 1) {
085:                    result = (Method) candidateMethods.get(0);
086:                } else {
087:                    result = searchCandidates(candidateMethods, bridgeMethod);
088:                }
089:
090:                if (result == null) {
091:                    throw new IllegalStateException(
092:                            "Unable to locate bridged method for bridge method '"
093:                                    + bridgeMethod + "'");
094:                }
095:
096:                return result;
097:            }
098:
099:            /**
100:             * Search for the bridged method in the given candidates.
101:             * @param candidateMethods the List of candidate Methods
102:             * @param bridgeMethod the bridge method
103:             * @return the bridged method, or <code>null</code> if none found
104:             */
105:            private static Method searchCandidates(List candidateMethods,
106:                    Method bridgeMethod) {
107:                Map typeParameterMap = createTypeVariableMap(bridgeMethod
108:                        .getDeclaringClass());
109:                for (int i = 0; i < candidateMethods.size(); i++) {
110:                    Method candidateMethod = (Method) candidateMethods.get(i);
111:                    if (isBridgeMethodFor(bridgeMethod, candidateMethod,
112:                            typeParameterMap)) {
113:                        return candidateMethod;
114:                    }
115:                }
116:                return null;
117:            }
118:
119:            /**
120:             * Return <code>true</code> if the supplied '<code>candidateMethod</code>' can be
121:             * consider a validate candidate for the {@link Method} that is {@link Method#isBridge() bridged}
122:             * by the supplied {@link Method bridge Method}. This method performs inexpensive
123:             * checks and can be used quickly filter for a set of possible matches.
124:             */
125:            private static boolean isBridgedCandidateFor(
126:                    Method candidateMethod, Method bridgeMethod) {
127:                return (!candidateMethod.isBridge()
128:                        && !candidateMethod.equals(bridgeMethod)
129:                        && candidateMethod.getName().equals(
130:                                bridgeMethod.getName()) && candidateMethod
131:                        .getParameterTypes().length == bridgeMethod
132:                        .getParameterTypes().length);
133:            }
134:
135:            /**
136:             * Determine whether or not the bridge {@link Method} is the bridge for the
137:             * supplied candidate {@link Method}.
138:             */
139:            static boolean isBridgeMethodFor(Method bridgeMethod,
140:                    Method candidateMethod, Map typeVariableMap) {
141:                if (isResolvedTypeMatch(candidateMethod, bridgeMethod,
142:                        typeVariableMap)) {
143:                    return true;
144:                }
145:                Method method = findGenericDeclaration(bridgeMethod);
146:                return (method != null ? isResolvedTypeMatch(method,
147:                        candidateMethod, typeVariableMap) : false);
148:            }
149:
150:            /**
151:             * Search for the generic {@link Method} declaration whose erased signature
152:             * matches that of the supplied bridge method.
153:             * @throws IllegalStateException if the generic declaration cannot be found
154:             */
155:            private static Method findGenericDeclaration(Method bridgeMethod) {
156:                // Search parent types for method that has same signature as bridge.
157:                Class super class = bridgeMethod.getDeclaringClass()
158:                        .getSuperclass();
159:                while (!Object.class.equals(super class)) {
160:                    Method method = searchForMatch(super class, bridgeMethod);
161:                    if (method != null && !method.isBridge()) {
162:                        return method;
163:                    }
164:                    super class = super class.getSuperclass();
165:                }
166:
167:                // Search interfaces.
168:                Class[] interfaces = ClassUtils
169:                        .getAllInterfacesForClass(bridgeMethod
170:                                .getDeclaringClass());
171:                for (int i = 0; i < interfaces.length; i++) {
172:                    Class anInterface = interfaces[i];
173:                    Method method = searchForMatch(anInterface, bridgeMethod);
174:                    if (method != null && !method.isBridge()) {
175:                        return method;
176:                    }
177:                }
178:
179:                return null;
180:            }
181:
182:            /**
183:             * Return <code>true</code> if the {@link Type} signature of both the supplied
184:             * {@link Method#getGenericParameterTypes() generic Method} and concrete {@link Method}
185:             * are equal after resolving all {@link TypeVariable TypeVariables} using the supplied
186:             * {@link #createTypeVariableMap TypeVariable Map}, otherwise returns <code>false</code>.
187:             */
188:            private static boolean isResolvedTypeMatch(Method genericMethod,
189:                    Method candidateMethod, Map typeVariableMap) {
190:                Type[] genericParameters = genericMethod
191:                        .getGenericParameterTypes();
192:                Class[] candidateParameters = candidateMethod
193:                        .getParameterTypes();
194:                if (genericParameters.length != candidateParameters.length) {
195:                    return false;
196:                }
197:                for (int i = 0; i < genericParameters.length; i++) {
198:                    Type genericParameter = genericParameters[i];
199:                    Class candidateParameter = candidateParameters[i];
200:                    if (candidateParameter.isArray()) {
201:                        // An array type: compare the component type.
202:                        Type rawType = getRawType(genericParameter,
203:                                typeVariableMap);
204:                        if (rawType instanceof  GenericArrayType) {
205:                            if (!candidateParameter.getComponentType().equals(
206:                                    getRawType(((GenericArrayType) rawType)
207:                                            .getGenericComponentType(),
208:                                            typeVariableMap))) {
209:                                return false;
210:                            }
211:                            break;
212:                        }
213:                    }
214:                    // A non-array type: compare the type itself.
215:                    if (!candidateParameter.equals(getRawType(genericParameter,
216:                            typeVariableMap))) {
217:                        return false;
218:                    }
219:                }
220:                return true;
221:            }
222:
223:            /**
224:             * Determine the raw type for the given generic parameter type.
225:             */
226:            private static Type getRawType(Type genericType, Map typeVariableMap) {
227:                if (genericType instanceof  TypeVariable) {
228:                    TypeVariable tv = (TypeVariable) genericType;
229:                    Type result = (Type) typeVariableMap.get(tv);
230:                    return (result != null ? result : Object.class);
231:                } else if (genericType instanceof  ParameterizedType) {
232:                    return ((ParameterizedType) genericType).getRawType();
233:                } else {
234:                    return genericType;
235:                }
236:            }
237:
238:            /**
239:             * If the supplied {@link Class} has a declared {@link Method} whose signature matches
240:             * that of the supplied {@link Method}, then this matching {@link Method} is returned,
241:             * otherwise <code>null</code> is returned.
242:             */
243:            private static Method searchForMatch(Class type, Method bridgeMethod) {
244:                return ReflectionUtils.findMethod(type, bridgeMethod.getName(),
245:                        bridgeMethod.getParameterTypes());
246:            }
247:
248:            /**
249:             * Build a mapping of {@link TypeVariable#getName TypeVariable names} to concrete
250:             * {@link Class} for the specified {@link Class}. Searches all super types,
251:             * enclosing types and interfaces.
252:             */
253:            static Map createTypeVariableMap(Class cls) {
254:                Map typeVariableMap = new HashMap();
255:
256:                // interfaces
257:                extractTypeVariablesFromGenericInterfaces(cls
258:                        .getGenericInterfaces(), typeVariableMap);
259:
260:                // super class
261:                Type genericType = cls.getGenericSuperclass();
262:                Class type = cls.getSuperclass();
263:                while (!Object.class.equals(type)) {
264:                    if (genericType instanceof  ParameterizedType) {
265:                        ParameterizedType pt = (ParameterizedType) genericType;
266:                        populateTypeMapFromParameterizedType(pt,
267:                                typeVariableMap);
268:                    }
269:                    extractTypeVariablesFromGenericInterfaces(type
270:                            .getGenericInterfaces(), typeVariableMap);
271:                    genericType = type.getGenericSuperclass();
272:                    type = type.getSuperclass();
273:                }
274:
275:                // enclosing class
276:                type = cls;
277:                while (type.isMemberClass()) {
278:                    genericType = type.getGenericSuperclass();
279:                    if (genericType instanceof  ParameterizedType) {
280:                        ParameterizedType pt = (ParameterizedType) genericType;
281:                        populateTypeMapFromParameterizedType(pt,
282:                                typeVariableMap);
283:                    }
284:                    type = type.getEnclosingClass();
285:                }
286:
287:                return typeVariableMap;
288:            }
289:
290:            private static void extractTypeVariablesFromGenericInterfaces(
291:                    Type[] genericInterfaces, Map typeVariableMap) {
292:                for (int i = 0; i < genericInterfaces.length; i++) {
293:                    Type genericInterface = genericInterfaces[i];
294:                    if (genericInterface instanceof  ParameterizedType) {
295:                        ParameterizedType pt = (ParameterizedType) genericInterface;
296:                        populateTypeMapFromParameterizedType(pt,
297:                                typeVariableMap);
298:                        if (pt.getRawType() instanceof  Class) {
299:                            extractTypeVariablesFromGenericInterfaces(
300:                                    ((Class) pt.getRawType())
301:                                            .getGenericInterfaces(),
302:                                    typeVariableMap);
303:                        }
304:                    } else if (genericInterface instanceof  Class) {
305:                        extractTypeVariablesFromGenericInterfaces(
306:                                ((Class) genericInterface)
307:                                        .getGenericInterfaces(),
308:                                typeVariableMap);
309:                    }
310:                }
311:            }
312:
313:            /**
314:             * Read the {@link TypeVariable TypeVariables} from the supplied {@link ParameterizedType}
315:             * and add mappings corresponding to the {@link TypeVariable#getName TypeVariable name} ->
316:             * concrete type to the supplied {@link Map}.
317:             * <p>Consider this case:
318:             * <pre class="code>
319:             * public interface Foo<S, T> {
320:             *  ..
321:             * }
322:             *
323:             * public class FooImpl implements Foo<String, Integer> {
324:             *  ..
325:             * }</pre>
326:             * For '<code>FooImpl</code>' the following mappings would be added to the {@link Map}:
327:             * {S=java.lang.String, T=java.lang.Integer}.
328:             */
329:            private static void populateTypeMapFromParameterizedType(
330:                    ParameterizedType type, Map typeVariableMap) {
331:                if (type.getRawType() instanceof  Class) {
332:                    Type[] actualTypeArguments = type.getActualTypeArguments();
333:                    TypeVariable[] typeVariables = ((Class) type.getRawType())
334:                            .getTypeParameters();
335:                    for (int i = 0; i < actualTypeArguments.length; i++) {
336:                        Type actualTypeArgument = actualTypeArguments[i];
337:                        TypeVariable variable = typeVariables[i];
338:                        if (actualTypeArgument instanceof  Class) {
339:                            typeVariableMap.put(variable, actualTypeArgument);
340:                        } else if (actualTypeArgument instanceof  GenericArrayType) {
341:                            typeVariableMap.put(variable, actualTypeArgument);
342:                        } else if (actualTypeArgument instanceof  ParameterizedType) {
343:                            typeVariableMap.put(variable,
344:                                    ((ParameterizedType) actualTypeArgument)
345:                                            .getRawType());
346:                        } else if (actualTypeArgument instanceof  TypeVariable) {
347:                            // We have a type that is parameterized at instantiation time
348:                            // the nearest match on the bridge method will be the bounded type.
349:                            TypeVariable typeVariableArgument = (TypeVariable) actualTypeArgument;
350:                            Type resolvedType = (Type) typeVariableMap
351:                                    .get(typeVariableArgument);
352:                            if (resolvedType == null) {
353:                                resolvedType = extractClassForTypeVariable(typeVariableArgument);
354:                            }
355:                            if (resolvedType != null) {
356:                                typeVariableMap.put(variable, resolvedType);
357:                            }
358:                        }
359:                    }
360:                }
361:            }
362:
363:            /**
364:             * Extracts the bound '<code>Class</code>' for a give {@link TypeVariable}.
365:             */
366:            private static Class extractClassForTypeVariable(
367:                    TypeVariable typeVariable) {
368:                Type[] bounds = typeVariable.getBounds();
369:                Type result = null;
370:                if (bounds.length > 0) {
371:                    Type bound = bounds[0];
372:                    if (bound instanceof  ParameterizedType) {
373:                        result = ((ParameterizedType) bound).getRawType();
374:                    } else if (bound instanceof  Class) {
375:                        result = bound;
376:                    } else if (bound instanceof  TypeVariable) {
377:                        result = extractClassForTypeVariable((TypeVariable) bound);
378:                    }
379:                }
380:                return (result instanceof  Class ? (Class) result : null);
381:            }
382:
383:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.