Source Code Cross Referenced for TypeResolver.java in  » 6.0-JDK-Modules-com.sun » beans » com » sun » beans » 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 » 6.0 JDK Modules com.sun » beans » com.sun.beans 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2003-2006 Sun Microsystems, Inc.  All Rights Reserved.
003:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004:         *
005:         * This code is free software; you can redistribute it and/or modify it
006:         * under the terms of the GNU General Public License version 2 only, as
007:         * published by the Free Software Foundation.  Sun designates this
008:         * particular file as subject to the "Classpath" exception as provided
009:         * by Sun in the LICENSE file that accompanied this code.
010:         *
011:         * This code is distributed in the hope that it will be useful, but WITHOUT
012:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014:         * version 2 for more details (a copy is included in the LICENSE file that
015:         * accompanied this code).
016:         *
017:         * You should have received a copy of the GNU General Public License version
018:         * 2 along with this work; if not, write to the Free Software Foundation,
019:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020:         *
021:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022:         * CA 95054 USA or visit www.sun.com if you need additional information or
023:         * have any questions.
024:         */
025:        package com.sun.beans;
026:
027:        import java.lang.reflect.Array;
028:        import java.lang.reflect.GenericArrayType;
029:        import java.lang.reflect.ParameterizedType;
030:        import java.lang.reflect.Type;
031:        import java.lang.reflect.TypeVariable;
032:        import java.lang.reflect.WildcardType;
033:        import java.util.HashMap;
034:        import java.util.Map;
035:
036:        import sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl;
037:        import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;
038:
039:        /**
040:         * This is utility class to resolve types.
041:         *
042:         * @since 1.7
043:         *
044:         * @version 1.1 06/06/07
045:         * @author Eamonn McManus
046:         * @author Sergey Malenkov
047:         */
048:        public final class TypeResolver {
049:            /**
050:             * Replaces the given {@code type} in an inherited method
051:             * with the actual type it has in the given {@code inClass}.
052:             *
053:             * <p>Although type parameters are not inherited by subclasses in the Java
054:             * language, they <em>are</em> effectively inherited when using reflection.
055:             * For example, if you declare an interface like this...</p>
056:             *
057:             * <pre>
058:             * public interface StringToIntMap extends Map&lt;String,Integer> {}
059:             * </pre>
060:             *
061:             * <p>...then StringToIntMap.class.getMethods() will show that it has methods
062:             * like put(K,V) even though StringToIntMap has no type parameters.  The K
063:             * and V variables are the ones declared by Map, so
064:             * {@link TypeVariable#getGenericDeclaration()} will return Map.class.</p>
065:             *
066:             * <p>The purpose of this method is to take a Type from a possibly-inherited
067:             * method and replace it with the correct Type for the inheriting class.
068:             * So given parameters of K and StringToIntMap.class in the above example,
069:             * this method will return String.</p>
070:             *
071:             * @param inClass  the base class used to resolve
072:             * @param type     the type to resolve
073:             * @return a resolved type
074:             *
075:             * @see #getActualType(Class)
076:             * @see #resolve(Type,Type)
077:             */
078:            public static Type resolveInClass(Class<?> inClass, Type type) {
079:                return resolve(getActualType(inClass), type);
080:            }
081:
082:            /**
083:             * Replaces all {@code types} in the given array
084:             * with the actual types they have in the given {@code inClass}.
085:             *
086:             * @param inClass  the base class used to resolve
087:             * @param types    the array of types to resolve
088:             * @return an array of resolved types
089:             *
090:             * @see #getActualType(Class)
091:             * @see #resolve(Type,Type[])
092:             */
093:            public static Type[] resolveInClass(Class<?> inClass, Type[] types) {
094:                return resolve(getActualType(inClass), types);
095:            }
096:
097:            /**
098:             * Replaces type variables of the given {@code formal} type
099:             * with the types they stand for in the given {@code actual} type.
100:             *
101:             * <p>A ParameterizedType is a class with type parameters, and the values
102:             * of those parameters.  For example, Map&lt;K,V> is a generic class, and
103:             * a corresponding ParameterizedType might look like
104:             * Map&lt;K=String,V=Integer>.  Given such a ParameterizedType, this method
105:             * will replace K with String, or List&lt;K> with List&ltString;, or
106:             * List&lt;? super K> with List&lt;? super String>.</p>
107:             *
108:             * <p>The {@code actual} argument to this method can also be a Class.
109:             * In this case, either it is equivalent to a ParameterizedType with
110:             * no parameters (for example, Integer.class), or it is equivalent to
111:             * a "raw" ParameterizedType (for example, Map.class).  In the latter
112:             * case, every type parameter declared or inherited by the class is replaced
113:             * by its "erasure".  For a type parameter declared as &lt;T>, the erasure
114:             * is Object.  For a type parameter declared as &lt;T extends Number>,
115:             * the erasure is Number.</p>
116:             *
117:             * <p>Although type parameters are not inherited by subclasses in the Java
118:             * language, they <em>are</em> effectively inherited when using reflection.
119:             * For example, if you declare an interface like this...</p>
120:             *
121:             * <pre>
122:             * public interface StringToIntMap extends Map&lt;String,Integer> {}
123:             * </pre>
124:             *
125:             * <p>...then StringToIntMap.class.getMethods() will show that it has methods
126:             * like put(K,V) even though StringToIntMap has no type parameters.  The K
127:             * and V variables are the ones declared by Map, so
128:             * {@link TypeVariable#getGenericDeclaration()} will return {@link Map Map.class}.</p>
129:             *
130:             * <p>For this reason, this method replaces inherited type parameters too.
131:             * Therefore if this method is called with {@code actual} being
132:             * StringToIntMap.class and {@code formal} being the K from Map,
133:             * it will return {@link String String.class}.</p>
134:             *
135:             * <p>In the case where {@code actual} is a "raw" ParameterizedType, the
136:             * inherited type parameters will also be replaced by their erasures.
137:             * The erasure of a Class is the Class itself, so a "raw" subinterface of
138:             * StringToIntMap will still show the K from Map as String.class.  But
139:             * in a case like this...
140:             *
141:             * <pre>
142:             * public interface StringToIntListMap extends Map&lt;String,List&lt;Integer>> {}
143:             * public interface RawStringToIntListMap extends StringToIntListMap {}
144:             * </pre>
145:             *
146:             * <p>...the V inherited from Map will show up as List&lt;Integer> in
147:             * StringToIntListMap, but as plain List in RawStringToIntListMap.</p>
148:             *
149:             * @param actual  the type that supplies bindings for type variables
150:             * @param formal  the type where occurrences of the variables
151:             *                in {@code actual} will be replaced by the corresponding bound values
152:             * @return a resolved type
153:             *
154:             * @see #TypeResolver(Type)
155:             * @see #resolve(Type)
156:             */
157:            public static Type resolve(Type actual, Type formal) {
158:                return new TypeResolver(actual).resolve(formal);
159:            }
160:
161:            /**
162:             * Replaces type variables of all formal types in the given array
163:             * with the types they stand for in the given {@code actual} type.
164:             *
165:             * @param actual   the type that supplies bindings for type variables
166:             * @param formals  the array of types to resolve
167:             * @return an array of resolved types
168:             *
169:             * @see #TypeResolver(Type)
170:             * @see #resolve(Type[])
171:             */
172:            public static Type[] resolve(Type actual, Type[] formals) {
173:                return new TypeResolver(actual).resolve(formals);
174:            }
175:
176:            /**
177:             * Converts the given {@code type} to the corresponding class.
178:             * This method implements the concept of type erasure,
179:             * that is described in <a href="http://jscstage.sfbay.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.6">section 4.6</a>
180:             * of Java Language Specification.
181:             *
182:             * @param type  the array of types to convert
183:             * @return a corresponding class
184:             */
185:            public static Class<?> erase(Type type) {
186:                if (type instanceof  Class) {
187:                    return (Class<?>) type;
188:                }
189:                if (type instanceof  ParameterizedType) {
190:                    ParameterizedType pt = (ParameterizedType) type;
191:                    return (Class<?>) pt.getRawType();
192:                }
193:                if (type instanceof  TypeVariable) {
194:                    TypeVariable tv = (TypeVariable) type;
195:                    Type[] bounds = tv.getBounds();
196:                    return (0 < bounds.length) ? erase(bounds[0])
197:                            : Object.class;
198:                }
199:                if (type instanceof  WildcardType) {
200:                    WildcardType wt = (WildcardType) type;
201:                    Type[] bounds = wt.getUpperBounds();
202:                    return (0 < bounds.length) ? erase(bounds[0])
203:                            : Object.class;
204:                }
205:                if (type instanceof  GenericArrayType) {
206:                    GenericArrayType gat = (GenericArrayType) type;
207:                    return Array.newInstance(
208:                            erase(gat.getGenericComponentType()), 0).getClass();
209:                }
210:                throw new IllegalArgumentException("Unknown Type kind: "
211:                        + type.getClass());
212:            }
213:
214:            /**
215:             * Converts all {@code types} in the given array
216:             * to the corresponding classes.
217:             *
218:             * @param types  the array of types to convert
219:             * @return an array of corresponding classes
220:             *
221:             * @see #erase(Type)
222:             */
223:            public static Class[] erase(Type[] types) {
224:                int length = types.length;
225:                Class[] classes = new Class[length];
226:                for (int i = 0; i < length; i++) {
227:                    classes[i] = TypeResolver.erase(types[i]);
228:                }
229:                return classes;
230:            }
231:
232:            private final Map<TypeVariable<?>, Type> map = new HashMap<TypeVariable<?>, Type>();
233:
234:            /**
235:             * Constructs the type resolver for the given actual type.
236:             *
237:             * @param actual  the type that supplies bindings for type variables
238:             *
239:             * @see #prepare(Type)
240:             */
241:            private TypeResolver(Type actual) {
242:                prepare(actual);
243:            }
244:
245:            /**
246:             * Fills the map from type parameters
247:             * to types as seen by the given {@code type}.
248:             * The method is recursive because the {@code type}
249:             * inherits mappings from its parent classes and interfaces.
250:             * The {@code type} can be either a {@link Class Class}
251:             * or a {@link ParameterizedType ParameterizedType}.
252:             * If it is a {@link Class Class}, it is either equivalent
253:             * to a {@link ParameterizedType ParameterizedType} with no parameters,
254:             * or it represents the erasure of a {@link ParameterizedType ParameterizedType}.
255:             *
256:             * @param type  the next type in the hierarchy
257:             */
258:            private void prepare(Type type) {
259:                Class<?> raw = (Class<?>) ((type instanceof  Class<?>) ? type
260:                        : ((ParameterizedType) type).getRawType());
261:
262:                TypeVariable<?>[] formals = raw.getTypeParameters();
263:
264:                Type[] actuals = (type instanceof  Class<?>) ? formals
265:                        : ((ParameterizedType) type).getActualTypeArguments();
266:
267:                assert formals.length == actuals.length;
268:                for (int i = 0; i < formals.length; i++) {
269:                    this .map.put(formals[i], actuals[i]);
270:                }
271:                Type gSuperclass = raw.getGenericSuperclass();
272:                if (gSuperclass != null) {
273:                    prepare(gSuperclass);
274:                }
275:                for (Type gInterface : raw.getGenericInterfaces()) {
276:                    prepare(gInterface);
277:                }
278:                // If type is the raw version of a parameterized class, we type-erase
279:                // all of its type variables, including inherited ones.
280:                if (type instanceof  Class<?> && formals.length > 0) {
281:                    for (Map.Entry<TypeVariable<?>, Type> entry : this .map
282:                            .entrySet()) {
283:                        entry.setValue(erase(entry.getValue()));
284:                    }
285:                }
286:            }
287:
288:            /**
289:             * Replaces the given {@code formal} type
290:             * with the type it stand for in this type resolver.
291:             *
292:             * @param formal  the array of types to resolve
293:             * @return a resolved type
294:             */
295:            private Type resolve(Type formal) {
296:                if (formal instanceof  Class) {
297:                    return formal;
298:                }
299:                if (formal instanceof  GenericArrayType) {
300:                    Type comp = ((GenericArrayType) formal)
301:                            .getGenericComponentType();
302:                    comp = resolve(comp);
303:                    return (comp instanceof  Class) ? Array.newInstance(
304:                            (Class<?>) comp, 0).getClass()
305:                            : GenericArrayTypeImpl.make(comp);
306:                }
307:                if (formal instanceof  ParameterizedType) {
308:                    ParameterizedType fpt = (ParameterizedType) formal;
309:                    Type[] actuals = resolve(fpt.getActualTypeArguments());
310:                    return ParameterizedTypeImpl.make((Class<?>) fpt
311:                            .getRawType(), actuals, fpt.getOwnerType());
312:                }
313:                if (formal instanceof  WildcardType) {
314:                    WildcardType fwt = (WildcardType) formal;
315:                    Type[] upper = resolve(fwt.getUpperBounds());
316:                    Type[] lower = resolve(fwt.getLowerBounds());
317:                    return new WildcardTypeImpl(upper, lower);
318:                }
319:                if (!(formal instanceof  TypeVariable)) {
320:                    throw new IllegalArgumentException("Bad Type kind: "
321:                            + formal.getClass());
322:                }
323:                Type actual = this .map.get((TypeVariable) formal);
324:                if (actual == null || actual.equals(formal)) {
325:                    return formal;
326:                }
327:                actual = fixGenericArray(actual);
328:                return resolve(actual);
329:                // A variable can be bound to another variable that is itself bound
330:                // to something.  For example, given:
331:                // class Super<T> {...}
332:                // class Mid<X> extends Super<T> {...}
333:                // class Sub extends Mid<String>
334:                // the variable T is bound to X, which is in turn bound to String.
335:                // So if we have to resolve T, we need the tail recursion here.
336:            }
337:
338:            /**
339:             * Replaces all formal types in the given array
340:             * with the types they stand for in this type resolver.
341:             *
342:             * @param formals  the array of types to resolve
343:             * @return an array of resolved types
344:             *
345:             * @see #resolve(Type)
346:             */
347:            private Type[] resolve(Type[] formals) {
348:                int length = formals.length;
349:                Type[] actuals = new Type[length];
350:                for (int i = 0; i < length; i++) {
351:                    actuals[i] = resolve(formals[i]);
352:                }
353:                return actuals;
354:            }
355:
356:            /**
357:             * Replaces a {@link GenericArrayType GenericArrayType}
358:             * with plain array class where it is possible.
359:             * Bug <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5041784">5041784</a>
360:             * is that arrays of non-generic type sometimes show up
361:             * as {@link GenericArrayType GenericArrayType} when using reflection.
362:             * For example, a {@code String[]} might show up
363:             * as a {@link GenericArrayType GenericArrayType}
364:             * where {@link GenericArrayType#getGenericComponentType getGenericComponentType}
365:             * is {@code String.class}.  This violates the specification,
366:             * which says that {@link GenericArrayType GenericArrayType}
367:             * is used when the component type is a type variable or parameterized type.
368:             * We fit the specification here.
369:             *
370:             * @param type  the type to fix
371:             * @return a corresponding type for the generic array type,
372:             *         or the same type as {@code type}
373:             */
374:            private static Type fixGenericArray(Type type) {
375:                if (type instanceof  GenericArrayType) {
376:                    Type comp = ((GenericArrayType) type)
377:                            .getGenericComponentType();
378:                    comp = fixGenericArray(comp);
379:                    if (comp instanceof  Class) {
380:                        return Array.newInstance((Class<?>) comp, 0).getClass();
381:                    }
382:                }
383:                return type;
384:            }
385:
386:            /**
387:             * Replaces a {@link Class Class} with type parameters
388:             * with a {@link ParameterizedType ParameterizedType}
389:             * where every parameter is bound to itself.
390:             * When calling {@link #resolveInClass} in the context of {@code inClass},
391:             * we can't just pass {@code inClass} as the {@code actual} parameter,
392:             * because if {@code inClass} has type parameters
393:             * that would be interpreted as accessing the raw type,
394:             * so we would get unwanted erasure.
395:             * This is why we bind each parameter to itself.
396:             * If {@code inClass} does have type parameters and has methods
397:             * where those parameters appear in the return type or argument types,
398:             * we will correctly leave those types alone.
399:             *
400:             * @param inClass  the base class used to resolve
401:             * @return a parameterized type for the class,
402:             *         or the same class as {@code inClass}
403:             */
404:            private static Type getActualType(Class<?> inClass) {
405:                Type[] params = inClass.getTypeParameters();
406:                return (params.length == 0) ? inClass : ParameterizedTypeImpl
407:                        .make(inClass, params, inClass.getEnclosingClass());
408:            }
409:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.