Source Code Cross Referenced for TypeQualifierApplications.java in  » Code-Analyzer » findbugs » edu » umd » cs » findbugs » ba » jsr305 » 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 » Code Analyzer » findbugs » edu.umd.cs.findbugs.ba.jsr305 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * FindBugs - Find Bugs in Java programs
003:         * Copyright (C) 2003-2007 University of Maryland
004:         * 
005:         * This library is free software; you can redistribute it and/or
006:         * modify it under the terms of the GNU Lesser General Public
007:         * License as published by the Free Software Foundation; either
008:         * version 2.1 of the License, or (at your option) any later version.
009:         * 
010:         * This library is distributed in the hope that it will be useful,
011:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
012:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013:         * Lesser General Public License for more details.
014:         * 
015:         * You should have received a copy of the GNU Lesser General Public
016:         * License along with this library; if not, write to the Free Software
017:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
018:         */
019:
020:        package edu.umd.cs.findbugs.ba.jsr305;
021:
022:        import java.lang.annotation.ElementType;
023:        import java.util.Collection;
024:        import java.util.Collections;
025:        import java.util.HashMap;
026:        import java.util.HashSet;
027:        import java.util.Map;
028:        import java.util.Set;
029:
030:        import javax.annotation.meta.When;
031:
032:        import org.objectweb.asm.Opcodes;
033:        import org.objectweb.asm.Type;
034:
035:        import edu.umd.cs.findbugs.SystemProperties;
036:        import edu.umd.cs.findbugs.annotations.CheckForNull;
037:        import edu.umd.cs.findbugs.ba.AbstractClassMember;
038:        import edu.umd.cs.findbugs.ba.AnalysisContext;
039:        import edu.umd.cs.findbugs.ba.XMethod;
040:        import edu.umd.cs.findbugs.classfile.ClassDescriptor;
041:        import edu.umd.cs.findbugs.classfile.DescriptorFactory;
042:        import edu.umd.cs.findbugs.classfile.analysis.AnnotatedObject;
043:        import edu.umd.cs.findbugs.classfile.analysis.AnnotationValue;
044:        import edu.umd.cs.findbugs.classfile.analysis.EnumValue;
045:        import edu.umd.cs.findbugs.util.DualKeyHashMap;
046:
047:        /**
048:         * Figure out where and how type qualifier annotations are applied.
049:         * 
050:         * @author William Pugh
051:         * @author David Hovemeyer
052:         */
053:        public class TypeQualifierApplications {
054:            static final boolean DEBUG = SystemProperties
055:                    .getBoolean("ctq.applications.debug");
056:
057:            static class Data {
058:                /** Type qualifier annotations applied directly to methods/fields/classes/etc. */
059:                private Map<AnnotatedObject, Collection<AnnotationValue>> directObjectAnnotations = new HashMap<AnnotatedObject, Collection<AnnotationValue>>();
060:
061:                /** Type qualifier annotations applied directly to method parameters. */
062:                private DualKeyHashMap<XMethod, Integer, Collection<AnnotationValue>> directParameterAnnotations = new DualKeyHashMap<XMethod, Integer, Collection<AnnotationValue>>();
063:
064:                /**
065:                 * Map of TypeQualifierValues to maps containing, for each AnnotatedObject,
066:                 * the effective TypeQualifierAnnotation (if any) for that AnnotatedObject.
067:                 */
068:                private Map<TypeQualifierValue, Map<AnnotatedObject, TypeQualifierAnnotation>> effectiveObjectAnnotations = new HashMap<TypeQualifierValue, Map<AnnotatedObject, TypeQualifierAnnotation>>();
069:
070:                /**
071:                 * Map of TypeQualifierValues to maps containing, for each XMethod/parameter,
072:                 * the effective TypeQualifierAnnotation (if any) for that XMethod/parameter.
073:                 */
074:                private Map<TypeQualifierValue, DualKeyHashMap<XMethod, Integer, TypeQualifierAnnotation>> effectiveParameterAnnotations = new HashMap<TypeQualifierValue, DualKeyHashMap<XMethod, Integer, TypeQualifierAnnotation>>();
075:            }
076:
077:            static Data data = new Data();
078:
079:            private static Map<TypeQualifierValue, DualKeyHashMap<XMethod, Integer, TypeQualifierAnnotation>> getEffectiveParameterAnnotations() {
080:                return data.effectiveParameterAnnotations;
081:            }
082:
083:            private static Map<TypeQualifierValue, Map<AnnotatedObject, TypeQualifierAnnotation>> getEffectiveObjectAnnotations() {
084:                return data.effectiveObjectAnnotations;
085:            }
086:
087:            private static DualKeyHashMap<XMethod, Integer, Collection<AnnotationValue>> getDirectParameterAnnotations() {
088:                return data.directParameterAnnotations;
089:            }
090:
091:            private static Map<AnnotatedObject, Collection<AnnotationValue>> getDirectObjectAnnotations() {
092:                return data.directObjectAnnotations;
093:            }
094:
095:            /**
096:             * Get the direct annotations (if any) on given AnnotatedObject.
097:             * 
098:             * @param m an AnnotatedObject
099:             * @return Collection of AnnotationValues representing annotations directly
100:             *         applied to this AnnotatedObject
101:             */
102:            private static Collection<AnnotationValue> getDirectAnnotation(
103:                    AnnotatedObject m) {
104:                Collection<AnnotationValue> result = getDirectObjectAnnotations()
105:                        .get(m);
106:                if (result != null)
107:                    return result;
108:                if (m.getAnnotationDescriptors().isEmpty())
109:                    return Collections.emptyList();
110:                result = TypeQualifierResolver.resolveTypeQualifiers(m
111:                        .getAnnotations());
112:                if (result.size() == 0)
113:                    result = Collections.emptyList();
114:                getDirectObjectAnnotations().put(m, result);
115:                return result;
116:            }
117:
118:            /**
119:             * Get the direct annotations (if any) on given method parameter.
120:             * 
121:             * @param m         a method
122:             * @param parameter a parameter (0 == first parameter)
123:             * @return Collection of AnnotationValues representing annotations directly
124:             *         applied to this parameter
125:             */
126:            private static Collection<AnnotationValue> getDirectAnnotation(
127:                    XMethod m, int parameter) {
128:                Collection<AnnotationValue> result = getDirectParameterAnnotations()
129:                        .get(m, parameter);
130:                if (result != null)
131:                    return result;
132:                if (m.getParameterAnnotationDescriptors(parameter).isEmpty())
133:                    return Collections.emptyList();
134:                result = TypeQualifierResolver.resolveTypeQualifiers(m
135:                        .getParameterAnnotations(parameter));
136:                if (result.size() == 0)
137:                    result = Collections.emptyList();
138:                getDirectParameterAnnotations().put(m, parameter, result);
139:                return result;
140:            }
141:
142:            /**
143:             * Populate a Set of TypeQualifierAnnotations representing
144:             * directly-applied type qualifier annotations on given
145:             * method parameter. 
146:             * 
147:             * @param result    Set of TypeQualifierAnnotations
148:             * @param o         a method
149:             * @param parameter a parameter (0 == first parameter)
150:             */
151:            private static void getDirectApplications(
152:                    Set<TypeQualifierAnnotation> result, XMethod o,
153:                    int parameter) {
154:                Collection<AnnotationValue> values = getDirectAnnotation(o,
155:                        parameter);
156:                ElementType e = ElementType.PARAMETER;
157:                for (AnnotationValue v : values) {
158:                    Object a = v.getValue("applyTo");
159:                    if (a instanceof  Object[]) {
160:                        for (Object o2 : (Object[]) a)
161:                            if (o2 instanceof  EnumValue) {
162:                                EnumValue ev = (EnumValue) o2;
163:                                if (ev.desc.getClassName().equals(
164:                                        "java/lang/annotation/ElementType")
165:                                        && e.toString().equals(ev.value))
166:                                    constructTypeQualifierAnnotation(result, v);
167:                            }
168:                    } else
169:                        constructTypeQualifierAnnotation(result, v);
170:                }
171:            }
172:
173:            /**
174:             * Populate a Set of TypeQualifierAnnotations representing
175:             * directly-applied type qualifier annotations on given
176:             * AnnotatedObject. 
177:             * 
178:             * @param result Set of TypeQualifierAnnotations
179:             * @param o      an AnnotatedObject
180:             * @param e      ElementType representing kind of annotated object
181:             */
182:            private static void getDirectApplications(
183:                    Set<TypeQualifierAnnotation> result, AnnotatedObject o,
184:                    ElementType e) {
185:                Collection<AnnotationValue> values = getDirectAnnotation(o);
186:                for (AnnotationValue v : values) {
187:                    Object a = v.getValue("applyTo");
188:                    if (a instanceof  Object[]) {
189:                        for (Object o2 : (Object[]) a)
190:                            if (o2 instanceof  EnumValue) {
191:                                EnumValue ev = (EnumValue) o2;
192:                                if (ev.desc.getClassName().equals(
193:                                        "java/lang/annotation/ElementType")
194:                                        && e.toString().equals(ev.value))
195:                                    constructTypeQualifierAnnotation(result, v);
196:                            }
197:                    } else if (o.getElementType().equals(e))
198:                        constructTypeQualifierAnnotation(result, v);
199:                }
200:            }
201:
202:            /**
203:             * Resolve a raw AnnotationValue into a TypeQualifierAnnotation.
204:             * 
205:             * @param v   a raw AnnotationValue
206:             * @return a constructed TypeQualifierAnnotation
207:             */
208:            public static TypeQualifierAnnotation constructTypeQualifierAnnotation(
209:                    AnnotationValue v) {
210:                assert v != null;
211:                EnumValue whenValue = (EnumValue) v.getValue("when");
212:                When when = whenValue == null ? When.ALWAYS : When
213:                        .valueOf(whenValue.value);
214:                ClassDescriptor annotationClass = v.getAnnotationClass();
215:                TypeQualifierValue tqv = TypeQualifierValue.getValue(
216:                        annotationClass, v.getValue("value"));
217:                TypeQualifierAnnotation tqa = TypeQualifierAnnotation.getValue(
218:                        tqv, when);
219:                return tqa;
220:            }
221:
222:            /**
223:             * Resolve a raw AnnotationValue into a TypeQualifierAnnotation,
224:             * storing result in given Set.
225:             * 
226:             * @param set Set of resolved TypeQualifierAnnotations
227:             * @param v   a raw AnnotationValue
228:             */
229:            public static void constructTypeQualifierAnnotation(
230:                    Set<TypeQualifierAnnotation> set, AnnotationValue v) {
231:                assert set != null;
232:                TypeQualifierAnnotation tqa = constructTypeQualifierAnnotation(v);
233:                set.add(tqa);
234:            }
235:
236:            /**
237:             * Populate Set of TypeQualifierAnnotations
238:             * for given AnnotatedObject,
239:             * taking into account annotations
240:             * applied to outer scopes (e.g., enclosing classes and packages.)
241:             * 
242:             * @param result Set of TypeQualifierAnnotations
243:             * @param o      an AnnotatedObject
244:             * @param e      ElementType representing kind of AnnotatedObject
245:             */
246:            private static void getApplicableScopedApplications(
247:                    Set<TypeQualifierAnnotation> result, AnnotatedObject o,
248:                    ElementType e) {
249:                AnnotatedObject outer = o.getContainingScope();
250:                if (outer != null)
251:                    getApplicableScopedApplications(result, outer, e);
252:                getDirectApplications(result, o, e);
253:            }
254:
255:            /**
256:             * Get the collection of resolved TypeQualifierAnnotations for
257:             * a given AnnotatedObject,
258:             * taking into account annotations
259:             * applied to outer scopes (e.g., enclosing classes and packages.)
260:             * 
261:             * @param o an AnnotatedObject
262:             * @param e ElementType representing kind of AnnotatedObject
263:             * @return Collection of resolved TypeQualifierAnnotations
264:             */
265:            private static Collection<TypeQualifierAnnotation> getApplicableScopedApplications(
266:                    AnnotatedObject o, ElementType e) {
267:                Set<TypeQualifierAnnotation> result = new HashSet<TypeQualifierAnnotation>();
268:                getApplicableScopedApplications(result, o, e);
269:                return result;
270:            }
271:
272:            /**
273:             * Get the collection of resolved TypeQualifierAnnotations for
274:             * a given parameter,
275:             * taking into account annotations
276:             * applied to outer scopes (e.g., enclosing classes and packages.)
277:             * 
278:             * @param o         a method
279:             * @param parameter a parameter (0 == first parameter)
280:             * @return Collection of resolved TypeQualifierAnnotations
281:             */
282:            private static Collection<TypeQualifierAnnotation> getApplicableScopedApplications(
283:                    XMethod o, int parameter) {
284:                Set<TypeQualifierAnnotation> result = new HashSet<TypeQualifierAnnotation>();
285:                ElementType e = ElementType.PARAMETER;
286:                getApplicableScopedApplications(result, o, e);
287:                getDirectApplications(result, o, parameter);
288:                return result;
289:            }
290:
291:            /**
292:             * Get the Collection of resolved TypeQualifierAnnotations representing
293:             * directly applied and default (outer scope) type qualifier annotations
294:             * for given AnnotatedObject.
295:             * 
296:             * <p>NOTE: does not properly account for inherited annotations
297:             * on instance methods.
298:             * It is ok to call this method to find out generally-relevant TypeQualifierAnnotations,
299:             * but not to find the effective TypeQualifierAnnotation.</p>
300:             * 
301:             * @param o an AnnotatedObject
302:             * @return Collection of TypeQualifierAnnotations applicable to the AnnotatedObject
303:             */
304:            public static Collection<TypeQualifierAnnotation> getApplicableApplications(
305:                    AnnotatedObject o) {
306:                return getApplicableScopedApplications(o, o.getElementType());
307:            }
308:
309:            /**
310:             * Get the Collection of resolved TypeQualifierAnnotations representing
311:             * directly applied and default (outer scope) type qualifier annotations
312:             * for given method parameter.
313:             * 
314:             * <p>NOTE: does not properly account for inherited annotations
315:             * on instance method parameters.
316:             * It is ok to call this method to find out generally-relevant TypeQualifierAnnotations,
317:             * but not to find the effective TypeQualifierAnnotation.</p>
318:             * 
319:             * @param o         a method
320:             * @param parameter a parameter (0 == first parameter)
321:             * @return Collection of TypeQualifierAnnotations applicable to the method parameter
322:             */
323:            public static Collection<TypeQualifierAnnotation> getApplicableApplications(
324:                    XMethod o, int parameter) {
325:                return getApplicableScopedApplications(o, parameter);
326:            }
327:
328:            /**
329:             * Look up a TypeQualifierAnnotation matching given TypeQualifierValue.
330:             * 
331:             * @param typeQualifierAnnotations a Collection of TypeQualifierAnnotations 
332:             * @param typeQualifierValue       a TypeQualifierValue
333:             * @return matching TypeQualifierAnnotation, or null if none
334:             */
335:            private static @CheckForNull
336:            TypeQualifierAnnotation findMatchingTypeQualifierAnnotation(
337:                    Collection<TypeQualifierAnnotation> typeQualifierAnnotations,
338:                    TypeQualifierValue typeQualifierValue) {
339:                for (TypeQualifierAnnotation typeQualifierAnnotation : typeQualifierAnnotations) {
340:                    if (typeQualifierAnnotation.typeQualifier
341:                            .equals(typeQualifierValue)) {
342:                        return typeQualifierAnnotation;
343:                    }
344:                }
345:                return null;
346:            }
347:
348:            /**
349:             * Check to see if one of the FindBugs-specific default annotation mechanisms
350:             * is used on given AnnotatedObject to define a default value for
351:             * given TypeQualifierValue. 
352:             * 
353:             * @param o                  an AnnotatedObject
354:             * @param typeQualifierValue a TypeQualifierValue
355:             * @param elementType        type of annotated element
356:             * @return default TypeQualifierAnnotation, or null if none 
357:             */
358:            private static @CheckForNull
359:            TypeQualifierAnnotation getFindBugsDefaultAnnotation(
360:                    AnnotatedObject o, TypeQualifierValue typeQualifierValue,
361:                    ElementType elementType) {
362:                TypeQualifierAnnotation result;
363:                Collection<AnnotationValue> values = TypeQualifierResolver
364:                        .resolveTypeQualifierDefaults(o.getAnnotations(),
365:                                elementType);
366:                TypeQualifierAnnotation tqa = extractAnnotation(values,
367:                        typeQualifierValue);
368:                if (tqa != null)
369:                    return tqa;
370:
371:                if ((result = checkFindBugsDefaultAnnotation(
372:                        FindBugsDefaultAnnotations.DEFAULT_ANNOTATION, o,
373:                        typeQualifierValue)) != null) {
374:                    return result;
375:                }
376:
377:                switch (elementType) {
378:                case FIELD:
379:                    result = checkFindBugsDefaultAnnotation(
380:                            FindBugsDefaultAnnotations.DEFAULT_ANNOTATION_FOR_FIELDS,
381:                            o, typeQualifierValue);
382:                    break;
383:                case METHOD:
384:                    result = checkFindBugsDefaultAnnotation(
385:                            FindBugsDefaultAnnotations.DEFAULT_ANNOTATION_FOR_METHODS,
386:                            o, typeQualifierValue);
387:                    break;
388:                case PARAMETER:
389:                    result = checkFindBugsDefaultAnnotation(
390:                            FindBugsDefaultAnnotations.DEFAULT_ANNOTATION_FOR_PARAMETERS,
391:                            o, typeQualifierValue);
392:                    break;
393:                default:
394:                    // ignore
395:                }
396:
397:                return result;
398:            }
399:
400:            private static @CheckForNull
401:            TypeQualifierAnnotation checkFindBugsDefaultAnnotation(
402:                    ClassDescriptor defaultAnnotation, AnnotatedObject o,
403:                    TypeQualifierValue typeQualifierValue) {
404:
405:                if (DEBUG) {
406:                    System.out.println("Checking for " + defaultAnnotation
407:                            + " containing " + typeQualifierValue + " on " + o);
408:                }
409:                // - check to see if default annotation is present; if not, return null
410:                AnnotationValue annotationValue = o
411:                        .getAnnotation(defaultAnnotation);
412:                if (annotationValue == null) {
413:                    if (DEBUG) {
414:                        System.out.println("   ===> no " + defaultAnnotation);
415:                    }
416:                    return null;
417:                }
418:
419:                // - get value - should be Type or array of Type
420:                Object value = annotationValue.getValue("value");
421:                if (value == null) {
422:                    if (DEBUG) {
423:                        System.out.println("   ===> value is null");
424:                    }
425:                    return null;
426:                }
427:                Object[] types;
428:                if (value instanceof  Object[]) {
429:                    types = (Object[]) value;
430:                } else {
431:                    types = new Object[] { value };
432:                }
433:
434:                // - scan through array elements; see if any match the TypeQualifierValue (including type qualifier nicknames)
435:                for (Object obj : types) {
436:                    if (!(obj instanceof  Type)) {
437:                        if (DEBUG) {
438:                            System.out
439:                                    .println("Found a non-Type value in value array of "
440:                                            + defaultAnnotation.toString()
441:                                            + " annotation");
442:                        }
443:                        continue;
444:                    }
445:
446:                    Type type = (Type) obj;
447:                    if (DEBUG) {
448:                        System.out.println("  ===> checking "
449:                                + type.getDescriptor());
450:                    }
451:                    if (type.getDescriptor().startsWith("[")) {
452:                        continue;
453:                    }
454:                    ClassDescriptor typeDesc = DescriptorFactory.instance()
455:                            .getClassDescriptor(type.getInternalName());
456:
457:                    // There is no general way to figure out whether a particular
458:                    // type is a type qualifier we're interested in without
459:                    // resolving it.
460:                    AnnotationValue annotation = new AnnotationValue(typeDesc);
461:                    Collection<AnnotationValue> resolvedTypeQualifiers = TypeQualifierResolver
462:                            .resolveTypeQualifiers(annotation);
463:                    TypeQualifierAnnotation tqa = extractAnnotation(
464:                            resolvedTypeQualifiers, typeQualifierValue);
465:                    if (tqa != null)
466:                        return tqa;
467:
468:                }
469:
470:                return null;
471:            }
472:
473:            private static TypeQualifierAnnotation extractAnnotation(
474:                    Collection<AnnotationValue> resolvedTypeQualifiers,
475:                    TypeQualifierValue typeQualifierValue) {
476:                for (AnnotationValue typeQualifier : resolvedTypeQualifiers) {
477:                    TypeQualifierAnnotation tqa = constructTypeQualifierAnnotation(typeQualifier);
478:                    if (tqa.typeQualifier.equals(typeQualifierValue)) {
479:                        if (DEBUG) {
480:                            System.out.println("  ===> Found match " + tqa);
481:                        }
482:                        return tqa;
483:                    }
484:                }
485:                return null;
486:            }
487:
488:            /**
489:             * Get the effective TypeQualifierAnnotation on given
490:             * AnnotatedObject.  Takes into account inherited and
491:             * default (outer scope) annotations.
492:             * 
493:             * @param o                  an AnnotatedObject
494:             * @param typeQualifierValue a TypeQualifierValue specifying kind of annotation
495:             *                           we want to look up
496:             * @return the effective TypeQualifierAnnotation, or null if
497:             *         there is no effective TypeQualifierAnnotation on this
498:             *         AnnotatedObject
499:             */
500:            public static TypeQualifierAnnotation getEffectiveTypeQualifierAnnotation(
501:                    AnnotatedObject o, TypeQualifierValue typeQualifierValue) {
502:                if (DEBUG) {
503:                    System.out.println("Looking up application of "
504:                            + typeQualifierValue + " on " + o);
505:                }
506:
507:                Map<AnnotatedObject, TypeQualifierAnnotation> map = getEffectiveObjectAnnotations()
508:                        .get(typeQualifierValue);
509:                if (map == null) {
510:                    map = new HashMap<AnnotatedObject, TypeQualifierAnnotation>();
511:                    getEffectiveObjectAnnotations()
512:                            .put(typeQualifierValue, map);
513:                }
514:
515:                // Check cached answer
516:                TypeQualifierAnnotation result;
517:
518:                if (map.containsKey(o)) {
519:                    result = map.get(o);
520:                } else {
521:                    // Compute answer
522:
523:                    TypeQualifierAnnotation tqa;
524:
525:                    // See if there is a direct application
526:                    tqa = getDirectTypeQualifierAnnotation(o,
527:                            typeQualifierValue);
528:
529:                    // If it's an instance method, check for an inherited annotation
530:                    if (tqa == null && (o instanceof  XMethod)
531:                            && !((XMethod) o).isStatic()) {
532:                        tqa = getInheritedTypeQualifierAnnotation((XMethod) o,
533:                                typeQualifierValue);
534:                    }
535:
536:                    // Check for a default (outer scope) annotation
537:                    if (tqa == null) {
538:                        tqa = getDefaultTypeQualifierAnnotation(o,
539:                                typeQualifierValue);
540:                    }
541:
542:                    // Cache computed answer
543:                    result = tqa;
544:                    map.put(o, result);
545:                }
546:                if (DEBUG) {
547:                    System.out.println("  => Answer: " + result);
548:                }
549:
550:                // Return cached answer
551:                return result;
552:            }
553:
554:            /**
555:             * Get a directly-applied TypeQualifierAnnotation on given AnnotatedObject.
556:             * 
557:             * @param o                  an AnnotatedObject
558:             * @param typeQualifierValue the kind of TypeQualifierValue we are looking for
559:             * @return directly-applied TypeQualifierAnnotation, or null if there is no
560:             *         such annotation on the AnnotatedObject
561:             */
562:            private static TypeQualifierAnnotation getDirectTypeQualifierAnnotation(
563:                    AnnotatedObject o, TypeQualifierValue typeQualifierValue) {
564:                TypeQualifierAnnotation result;
565:
566:                Set<TypeQualifierAnnotation> applications = new HashSet<TypeQualifierAnnotation>();
567:                getDirectApplications(applications, o, o.getElementType());
568:
569:                result = findMatchingTypeQualifierAnnotation(applications,
570:                        typeQualifierValue);
571:
572:                return result;
573:            }
574:
575:            /**
576:             * Get the effective inherited TypeQualifierAnnotation on given
577:             * instance method.
578:             * 
579:             * @param o                  an XMethod
580:             * @param typeQualifierValue the kind of TypeQualifierValue we are looking for
581:             * @return effective TypeQualifierAnnotation inherited from overridden supertype methods,
582:             *         or null if there is no inherited TypeQualifierAnnotation
583:             */
584:            private static TypeQualifierAnnotation getInheritedTypeQualifierAnnotation(
585:                    XMethod o, TypeQualifierValue typeQualifierValue) {
586:                assert !o.isStatic();
587:
588:                ReturnTypeAnnotationAccumulator accumulator = new ReturnTypeAnnotationAccumulator(
589:                        typeQualifierValue, o);
590:                try {
591:                    AnalysisContext.currentAnalysisContext().getSubtypes2()
592:                            .traverseSupertypes(o.getClassDescriptor(),
593:                                    accumulator);
594:                    return accumulator.getResult()
595:                            .getEffectiveTypeQualifierAnnotation();
596:                } catch (ClassNotFoundException e) {
597:                    AnalysisContext.currentAnalysisContext()
598:                            .getLookupFailureCallback().reportMissingClass(e);
599:                    return null;
600:                }
601:            }
602:
603:            /**
604:             * Get the default (outer scope) annotation applicable to given
605:             * AnnotatedObject.
606:             * 
607:             * @param o                  an AnnotatedObject
608:             * @param typeQualifierValue the kind of TypeQualifierValue we are looking for
609:             * @return the applicable default TypeQualifierAnnotation, or null
610:             *         if there is no default TypeQualifierAnnotation
611:             */
612:            private static TypeQualifierAnnotation getDefaultTypeQualifierAnnotation(
613:                    AnnotatedObject o, TypeQualifierValue typeQualifierValue) {
614:
615:                if (o instanceof  AbstractClassMember
616:                        && (((AbstractClassMember) o).getAccessFlags() & Opcodes.ACC_SYNTHETIC) != 0)
617:                    return null; // synthetic methods don't get default annotations
618:                TypeQualifierAnnotation result = null;
619:
620:                ElementType elementType = o.getElementType();
621:                while (o.getContainingScope() != null) {
622:                    o = o.getContainingScope();
623:
624:                    // Check direct applications of the type qualifier
625:                    Set<TypeQualifierAnnotation> applications = new HashSet<TypeQualifierAnnotation>();
626:                    getDirectApplications(applications, o, elementType);
627:                    result = findMatchingTypeQualifierAnnotation(applications,
628:                            typeQualifierValue);
629:                    if (result != null) {
630:                        // Great - found an outer scope with a relevant annotation
631:                        break;
632:                    }
633:
634:                    // Check FindBugs-specific default annotations
635:                    result = getFindBugsDefaultAnnotation(o,
636:                            typeQualifierValue, elementType);
637:                    if (result != null) {
638:                        break;
639:                    }
640:                }
641:                return result;
642:            }
643:
644:            /**
645:             * Get the effective TypeQualifierAnnotation on given method parameter.
646:             * Takes into account inherited and default (outer scope) annotations.
647:             * 
648:             * @param xmethod            a method
649:             * @param parameter          a parameter (0 == first parameter)
650:             * @param typeQualifierValue the kind of TypeQualifierValue we are looking for
651:             * @return effective TypeQualifierAnnotation on the parameter,
652:             *         or null if there is no effective TypeQualifierAnnotation
653:             */
654:            public static @CheckForNull
655:            TypeQualifierAnnotation getEffectiveTypeQualifierAnnotation(
656:                    XMethod xmethod, int parameter,
657:                    TypeQualifierValue typeQualifierValue) {
658:                if (DEBUG) {
659:                    System.out.println("Looking up application of "
660:                            + typeQualifierValue + " on " + xmethod
661:                            + " parameter " + parameter);
662:                }
663:
664:                DualKeyHashMap<XMethod, Integer, TypeQualifierAnnotation> map = getEffectiveParameterAnnotations()
665:                        .get(typeQualifierValue);
666:                if (map == null) {
667:                    map = new DualKeyHashMap<XMethod, Integer, TypeQualifierAnnotation>();
668:                    getEffectiveParameterAnnotations().put(typeQualifierValue,
669:                            map);
670:                }
671:
672:                // Check cached answer
673:                TypeQualifierAnnotation result;
674:                if (map.containsKey(xmethod, parameter))
675:                    result = map.get(xmethod, parameter);
676:                else {
677:                    // Compute answer
678:                    TypeQualifierAnnotation tqa;
679:
680:                    // Check direct application
681:                    tqa = getDirectTypeQualifierAnnotation(xmethod, parameter,
682:                            typeQualifierValue);
683:
684:                    // If it's an instance method, check for inherited annotation
685:                    if (tqa == null && !xmethod.isStatic()) {
686:                        tqa = getInheritedTypeQualifierAnnotation(xmethod,
687:                                parameter, typeQualifierValue);
688:                    }
689:
690:                    // Check for default (outer scope) annotation
691:                    if (tqa == null) {
692:                        tqa = getDefaultTypeQualifierAnnotation(xmethod,
693:                                parameter, typeQualifierValue);
694:                    }
695:
696:                    // Cache answer
697:                    result = tqa;
698:                    map.put(xmethod, parameter, result);
699:                }
700:
701:                if (DEBUG) {
702:                    System.out.println("  => Answer: " + result);
703:                }
704:
705:                // Return cached answer
706:                return result;
707:            }
708:
709:            /**
710:             * Get the TypeQualifierAnnotation directly applied to given
711:             * method parameter.
712:             * 
713:             * @param xmethod            a method
714:             * @param parameter          a parameter (0 == first parameter)
715:             * @param typeQualifierValue the kind of TypeQualifierValue we are looking for
716:             * @return TypeQualifierAnnotation directly applied to the parameter,
717:             *         or null if there is no directly applied TypeQualifierAnnotation
718:             */
719:            private static @CheckForNull
720:            TypeQualifierAnnotation getDirectTypeQualifierAnnotation(
721:                    XMethod xmethod, int parameter,
722:                    TypeQualifierValue typeQualifierValue) {
723:                Set<TypeQualifierAnnotation> applications = new HashSet<TypeQualifierAnnotation>();
724:                getDirectApplications(applications, xmethod, parameter);
725:
726:                return findMatchingTypeQualifierAnnotation(applications,
727:                        typeQualifierValue);
728:            }
729:
730:            /**
731:             * Get the effective inherited TypeQualifierAnnotation on the given
732:             * instance method parameter.
733:             * 
734:             * @param xmethod            an instance method
735:             * @param parameter          a parameter (0 == first parameter)
736:             * @param typeQualifierValue the kind of TypeQualifierValue we are looking for
737:             * @return effective inherited TypeQualifierAnnotation on the parameter,
738:             *         or null if there is not effective TypeQualifierAnnotation
739:             */
740:            private static @CheckForNull
741:            TypeQualifierAnnotation getInheritedTypeQualifierAnnotation(
742:                    XMethod xmethod, int parameter,
743:                    TypeQualifierValue typeQualifierValue) {
744:                assert !xmethod.isStatic();
745:
746:                ParameterAnnotationAccumulator accumulator = new ParameterAnnotationAccumulator(
747:                        typeQualifierValue, xmethod, parameter);
748:                try {
749:                    AnalysisContext.currentAnalysisContext().getSubtypes2()
750:                            .traverseSupertypes(xmethod.getClassDescriptor(),
751:                                    accumulator);
752:                    return accumulator.getResult()
753:                            .getEffectiveTypeQualifierAnnotation();
754:                } catch (ClassNotFoundException e) {
755:                    AnalysisContext.currentAnalysisContext()
756:                            .getLookupFailureCallback().reportMissingClass(e);
757:                    return null;
758:                }
759:            }
760:
761:            /**
762:             * Get the default (outer-scope) TypeQualifierAnnotation on given method parameter.
763:             * 
764:             * @param xmethod            a method
765:             * @param parameter          a parameter (0 == first parameter)
766:             * @param typeQualifierValue the kind of TypeQualifierValue we are looking for
767:             * @return the default (outer scope) TypeQualifierAnnotation on the parameter,
768:             *         or null if there is no default TypeQualifierAnnotation
769:             */
770:            private static @CheckForNull
771:            TypeQualifierAnnotation getDefaultTypeQualifierAnnotation(
772:                    XMethod xmethod, int parameter,
773:                    TypeQualifierValue typeQualifierValue) {
774:
775:                if ((xmethod.getAccessFlags() & Opcodes.ACC_SYNTHETIC) != 0)
776:                    return null; // synthetic methods don't get default annotations
777:                AnnotatedObject o = xmethod;
778:
779:                while (o.getContainingScope() != null) {
780:                    o = o.getContainingScope();
781:
782:                    // Check for direct type qualifier annotation
783:                    Set<TypeQualifierAnnotation> applications = new HashSet<TypeQualifierAnnotation>();
784:                    getDirectApplications(applications, o,
785:                            ElementType.PARAMETER);
786:                    TypeQualifierAnnotation tqa = findMatchingTypeQualifierAnnotation(
787:                            applications, typeQualifierValue);
788:                    if (tqa != null) {
789:                        // Found matching annotation in outer scope
790:                        return tqa;
791:                    }
792:
793:                    // Check for FindBugs-specific default annotation
794:                    tqa = getFindBugsDefaultAnnotation(o, typeQualifierValue,
795:                            ElementType.PARAMETER);
796:                    if (tqa != null) {
797:                        return tqa;
798:                    }
799:                }
800:
801:                return null;
802:            }
803:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.