Source Code Cross Referenced for AnnotationReader.java in  » Net » Terracotta » com » tc » backport175 » bytecode » 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 » Net » Terracotta » com.tc.backport175.bytecode 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*******************************************************************************************
0002:         * Copyright (c) Jonas Bonér, Alexandre Vasseur. All rights reserved.                      *
0003:         * http://backport175.codehaus.org                                                         *
0004:         * --------------------------------------------------------------------------------------- *
0005:         * The software in this package is published under the terms of Apache License Version 2.0 *
0006:         * a copy of which has been included with this distribution in the license.txt file.       *
0007:         *******************************************************************************************/package com.tc.backport175.bytecode;
0008:
0009:        import com.tc.backport175.Annotation;
0010:        import com.tc.backport175.bytecode.spi.BytecodeProvider;
0011:        import com.tc.backport175.proxy.ProxyFactory;
0012:
0013:        import com.tc.asm.AnnotationVisitor;
0014:        import com.tc.asm.ClassReader;
0015:        import com.tc.asm.FieldVisitor;
0016:        import com.tc.asm.MethodVisitor;
0017:        import com.tc.asm.Type;
0018:        import com.tc.asm.commons.EmptyVisitor;
0019:
0020:        import java.lang.ref.Reference;
0021:        import java.lang.ref.WeakReference;
0022:        import java.lang.reflect.Constructor;
0023:        import java.lang.reflect.Field;
0024:        import java.lang.reflect.Method;
0025:        import java.util.Collection;
0026:        import java.util.HashMap;
0027:        import java.util.Iterator;
0028:        import java.util.Map;
0029:        import java.util.WeakHashMap;
0030:
0031:        /**
0032:         * Reads Java 5 {@link java.lang.annotation.RetentionPolicy.RUNTIME} and
0033:         * {@link java.lang.annotation.RetentionPolicy.CLASS} annotations from the class' bytecode.
0034:         * <p/>
0035:         * Can be used with a custom implementation of the {@link org.codehaus.backport175.reader.bytecode.spi.BytecodeProvider}
0036:         * interface.
0037:         * <p/>
0038:         * Note: does not handles {@link java.lang.annotation.Inherited} feature. This has to be done in the higher level
0039:         * that knows about the class hierarchy (see backport175.Annotations f.e)
0040:         *
0041:         * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér</a>
0042:         * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
0043:         */
0044:        public class AnnotationReader {
0045:
0046:            private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0];
0047:            private static final AnnotationElement.Annotation[] EMPTY_ANNOTATION_ELEMENT_ARRAY = new AnnotationElement.Annotation[0];
0048:            private static final String INIT_METHOD_NAME = "<init>";
0049:
0050:            private static final Map CLASS_SPECIFIC_BYTECODE_PROVIDER = new WeakHashMap();
0051:            private static BytecodeProvider BYTECODE_PROVIDER = new DefaultBytecodeProvider();
0052:
0053:            /**
0054:             * Key is ClassKey, value is WeakReference of AnnotationReader 
0055:             */
0056:            private static final Map READERS = new WeakHashMap();
0057:
0058:            private final ClassKey m_classKey;
0059:
0060:            // ===========================================================================
0061:            // Implementation notes:
0062:            // Parsing and annotation creation is made in two steps
0063:            //
0064:            // 1. The bytecode is parsed and the annotation content is put in elements,
0065:            //    which are stored for later processing
0066:            //
0067:            // 2. Upon annotation access the elements are processed and a dynamic proxy
0068:            //    for the annotation is created and cached.
0069:            //
0070:            // This gives much better performance than reflective access of Java 5
0071:            // annotations (reflective access is around 5 times slower)
0072:            // ===========================================================================
0073:
0074:            private final Map m_classAnnotationElements = new HashMap();
0075:            private final Map m_constructorAnnotationElements = new HashMap();
0076:            private final Map m_methodAnnotationElements = new HashMap();
0077:            private final Map m_fieldAnnotationElements = new HashMap();
0078:
0079:            private final Map m_classAnnotationCache = new HashMap();
0080:            private final Map m_constructorAnnotationCache = new HashMap();
0081:            private final Map m_methodAnnotationCache = new HashMap();
0082:            private final Map m_fieldAnnotationCache = new HashMap();
0083:
0084:            /**
0085:             * Sets the bytecode provider.
0086:             * <p/>
0087:             * If a custom provider is not set then a default impl will be used (which reads the bytecode from disk).
0088:             *
0089:             * @param bytecodeProvider
0090:             */
0091:            public static void setDefaultBytecodeProvider(
0092:                    final BytecodeProvider bytecodeProvider) {
0093:                BYTECODE_PROVIDER = bytecodeProvider;
0094:            }
0095:
0096:            /**
0097:             * Returns the bytecode provider.
0098:             *
0099:             * @return the bytecode provider
0100:             */
0101:            public static BytecodeProvider getDefaultBytecodeProvider() {
0102:                return BYTECODE_PROVIDER;
0103:            }
0104:
0105:            /**
0106:             * Sets the bytecode provider.
0107:             * <p/>
0108:             * If a custom provider is not set then a default impl will be used (which reads the bytecode from disk).
0109:             *
0110:             * @param klass
0111:             * @param bytecodeProvider
0112:             */
0113:            public static void setBytecodeProviderFor(final Class klass,
0114:                    final BytecodeProvider bytecodeProvider) {
0115:                setBytecodeProviderFor(klass.getName(), klass.getClassLoader(),
0116:                        bytecodeProvider);
0117:            }
0118:
0119:            /**
0120:             * Sets the bytecode provider.
0121:             * <p/>
0122:             * If a custom provider is not set then a default impl will be used (which reads the bytecode from disk).
0123:             *
0124:             * @param className
0125:             * @param loader
0126:             * @param bytecodeProvider
0127:             */
0128:            public static void setBytecodeProviderFor(final String className,
0129:                    final ClassLoader loader,
0130:                    final BytecodeProvider bytecodeProvider) {
0131:                CLASS_SPECIFIC_BYTECODE_PROVIDER.put(new ClassKey(className,
0132:                        loader), bytecodeProvider);
0133:            }
0134:
0135:            /**
0136:             * Returns the bytecode provider.
0137:             *
0138:             * @param klass
0139:             * @return the bytecode provider
0140:             */
0141:            public static BytecodeProvider getBytecodeProviderFor(
0142:                    final Class klass) {
0143:                return getBytecodeProviderFor(klass.getName(), klass
0144:                        .getClassLoader());
0145:            }
0146:
0147:            /**
0148:             * Returns the bytecode provider.
0149:             *
0150:             * @param className
0151:             * @param loader
0152:             * @return the bytecode provider
0153:             */
0154:            public static BytecodeProvider getBytecodeProviderFor(
0155:                    final String className, final ClassLoader loader) {
0156:                BytecodeProvider bytecodeProvider = (BytecodeProvider) CLASS_SPECIFIC_BYTECODE_PROVIDER
0157:                        .get(new ClassKey(className, loader));
0158:                if (bytecodeProvider == null) {
0159:                    return BYTECODE_PROVIDER;
0160:                }
0161:                return bytecodeProvider;
0162:            }
0163:
0164:            /**
0165:             * Returns the bytecode for a class.
0166:             *
0167:             * @param className
0168:             * @param loader
0169:             * @return the bytecode for a class
0170:             */
0171:            public static byte[] getBytecodeFor(final String className,
0172:                    final ClassLoader loader) throws Exception {
0173:                return getBytecodeProviderFor(className, loader).getBytecode(
0174:                        className, loader);
0175:            }
0176:
0177:            /**
0178:             * Returns the annotation reader for the class specified.
0179:             * <p/>
0180:             * The annotation reader is created and cached if non-existant.
0181:             *
0182:             * @param klass
0183:             * @return the annotation reader
0184:             */
0185:            public static AnnotationReader getReaderFor(final Class klass) {
0186:                return getReaderFor(new ClassKey(klass.getName(), klass
0187:                        .getClassLoader()));
0188:            }
0189:
0190:            /**
0191:             * Returns the annotation reader for the class specified.
0192:             * <p/>
0193:             * The annotation reader is created and cached if non-existant.
0194:             *
0195:             * @param className
0196:             * @param loader
0197:             * @return the annotation reader
0198:             */
0199:            public static AnnotationReader getReaderFor(final String className,
0200:                    final ClassLoader loader) {
0201:                return getReaderFor(new ClassKey(className, loader));
0202:            }
0203:
0204:            /**
0205:             * Returns the annotation reader for the class specified.
0206:             * <p/>
0207:             * The annotation reader is created and cached if non-existant.
0208:             *
0209:             * @param classKey
0210:             * @return the annotation reader
0211:             */
0212:            public static AnnotationReader getReaderFor(final ClassKey classKey) {
0213:                AnnotationReader reader;
0214:                Object value = READERS.get(classKey);
0215:                if (value == null) {
0216:                    synchronized (READERS) {
0217:                        reader = new AnnotationReader(classKey);
0218:                        READERS.put(classKey, new WeakReference(reader));//reader strong refs its own key in the weakhahsmap..
0219:                    }
0220:                } else {
0221:                    reader = (AnnotationReader) ((Reference) value).get();
0222:                    if (reader == null) {//WeakReference content can be null
0223:                        synchronized (READERS) {
0224:                            reader = new AnnotationReader(classKey);
0225:                            READERS.put(classKey, new WeakReference(reader));
0226:                        }
0227:                    }
0228:                }
0229:                return reader;
0230:            }
0231:
0232:            /**
0233:             * Resets the annotation reader for the class specified and triggers a new parsing of the newly read bytecode.
0234:             * <p/>
0235:             * This method calls <code>parse</code> and is therefore all the is needed to invoke to get a fully updated reader.
0236:             *
0237:             * @param klass
0238:             */
0239:            public static void refresh(final Class klass) {
0240:                AnnotationReader reader = getReaderFor(klass);
0241:                synchronized (reader) {
0242:                    reader.refresh();
0243:                }
0244:            }
0245:
0246:            /**
0247:             * Resets the annotation reader for the class specified and triggers a new parsing of the newly read bytecode.
0248:             * <p/>
0249:             * This method calls <code>parse</code> and is therefore all the is needed to invoke to get a fully updated reader.
0250:             *
0251:             * @param className
0252:             * @param loader
0253:             */
0254:            public static void refresh(final String className,
0255:                    final ClassLoader loader) {
0256:                AnnotationReader reader = getReaderFor(className, loader);
0257:                synchronized (reader) {
0258:                    reader.refresh();
0259:                }
0260:            }
0261:
0262:            /**
0263:             * Resets *all* the annotation reader and triggers a new parsing of the newly read bytecode.
0264:             * <p/>
0265:             * This method will force parsing of all classes bytecode which might be very time consuming, use with care.
0266:             * <p/>
0267:             * This method calls <code>parse</code> and is therefore all the is needed to invoke to get a fully updated reader.
0268:             */
0269:            public static void refreshAll() {
0270:                for (Iterator it = READERS.values().iterator(); it.hasNext();) {
0271:                    AnnotationReader reader = (AnnotationReader) ((Reference) it
0272:                            .next()).get();
0273:                    synchronized (reader) {
0274:                        reader.refresh();
0275:                    }
0276:                }
0277:            }
0278:
0279:            /**
0280:             * Converts the annotion class description to a Java class name.
0281:             * Caution: Does not handles array type or primitive.
0282:             *
0283:             * @param desc
0284:             * @return
0285:             */
0286:            public static String toJavaName(final String desc) {
0287:                return desc.substring(1, desc.length() - 1).replace('/', '.');
0288:            }
0289:
0290:            /**
0291:             * Checks if an annotation is present at a specific class.
0292:             *
0293:             * @param annotationName the annotation name
0294:             * @return true if the annotation is present else false
0295:             */
0296:            public boolean isAnnotationPresent(final String annotationName) {
0297:                return m_classAnnotationElements.containsKey(annotationName);
0298:            }
0299:
0300:            /**
0301:             * Returns the class annotation with the name specified.
0302:             *
0303:             * @param annotationName
0304:             * @return the class annotation
0305:             */
0306:            public Annotation getAnnotation(final String annotationName) {
0307:                Object cachedAnnotation = m_classAnnotationCache
0308:                        .get(annotationName);
0309:                if (cachedAnnotation != null) {
0310:                    return (Annotation) cachedAnnotation;
0311:                } else {
0312:                    final Annotation annotation;
0313:                    final AnnotationElement.Annotation annotationInfo = (AnnotationElement.Annotation) m_classAnnotationElements
0314:                            .get(annotationName);
0315:                    if (annotationInfo != null) {
0316:                        annotation = ProxyFactory.newAnnotationProxy(
0317:                                annotationInfo, m_classKey.getClassLoader());
0318:                        m_classAnnotationCache.put(annotationName, annotation);
0319:                        return annotation;
0320:                    } else {
0321:                        return null;
0322:                    }
0323:                }
0324:            }
0325:
0326:            /**
0327:             * Returns all the class annotations.
0328:             *
0329:             * @return an array with the class annotations
0330:             */
0331:            public Annotation[] getAnnotations() {
0332:                final Collection annotationNames = m_classAnnotationElements
0333:                        .keySet();
0334:                if (annotationNames.isEmpty()) {
0335:                    return EMPTY_ANNOTATION_ARRAY;
0336:                }
0337:                final Annotation[] annotations = new Annotation[annotationNames
0338:                        .size()];
0339:                int i = 0;
0340:                for (Iterator iterator = annotationNames.iterator(); iterator
0341:                        .hasNext();) {
0342:                    String annotationName = (String) iterator.next();
0343:                    annotations[i++] = getAnnotation(annotationName);
0344:                }
0345:                return annotations;
0346:            }
0347:
0348:            /**
0349:             * Checks if an annotation is present at a specific constructor.
0350:             *
0351:             * @param annotationName the annotation name
0352:             * @param constructor    the java.lang.reflect.Constructor object to find the annotations on.
0353:             * @return true if the annotation is present else false
0354:             */
0355:            public boolean isAnnotationPresent(final String annotationName,
0356:                    final Constructor constructor) {
0357:                final AnnotationReader.MemberKey key = AnnotationReader.MemberKey
0358:                        .newConstructorKey(constructor);
0359:                Object map = m_constructorAnnotationElements.get(key);
0360:                if (map != null) {
0361:                    if (((Map) map).containsKey(annotationName)) {
0362:                        return true;
0363:                    }
0364:                }
0365:                return false;
0366:            }
0367:
0368:            /**
0369:             * Returns the constructor annotation with the name specified for the constructor specified.
0370:             *
0371:             * @param annotationName the annotation name
0372:             * @param constructor    the java.lang.reflect.Constructor object to find the annotations on.
0373:             * @return the constructor annotation
0374:             */
0375:            public Annotation getAnnotation(final String annotationName,
0376:                    final Constructor constructor) {
0377:                return getConstructorAnnotation(annotationName, MemberKey
0378:                        .newConstructorKey(constructor), constructor
0379:                        .getDeclaringClass().getClassLoader());
0380:            }
0381:
0382:            /**
0383:             * Returns the constructor annotation with the name specified for the constructor specified.
0384:             *
0385:             * @param annotationName
0386:             * @param constructorDesc
0387:             * @param loader
0388:             * @return
0389:             */
0390:            public Annotation getConstructorAnnotation(
0391:                    final String annotationName, final String constructorDesc,
0392:                    final ClassLoader loader) {
0393:                return getConstructorAnnotation(annotationName, MemberKey
0394:                        .newConstructorKey(constructorDesc), loader);
0395:            }
0396:
0397:            /**
0398:             * Returns the constructor annotation with the name specified for the constructor specified.
0399:             *
0400:             * @param annotationName
0401:             * @param constructorKey
0402:             * @param loader
0403:             * @return
0404:             */
0405:            private Annotation getConstructorAnnotation(
0406:                    final String annotationName,
0407:                    final MemberKey constructorKey, final ClassLoader loader) {
0408:                Map annotationMap = getConstructorAnnotationCacheFor(constructorKey);
0409:                Object cachedAnnotation = annotationMap.get(annotationName);
0410:                if (cachedAnnotation != null) {
0411:                    return (Annotation) cachedAnnotation;
0412:                }
0413:                // not in cache - create a new DP and put in cache
0414:                final Map annotations = (Map) m_constructorAnnotationElements
0415:                        .get(constructorKey);
0416:                if (annotations == null) {
0417:                    // no such annotation
0418:                    return null;
0419:                }
0420:                Object annotationElement = annotations.get(annotationName);
0421:                if (annotationElement != null) {
0422:                    Annotation annotation = ProxyFactory.newAnnotationProxy(
0423:                            (AnnotationElement.Annotation) annotationElement,
0424:                            loader);
0425:                    annotationMap.put(annotationName, annotation);
0426:                    return annotation;
0427:                }
0428:                return null;
0429:            }
0430:
0431:            /**
0432:             * Returns all the constructor annotations.
0433:             *
0434:             * @param constructor the java.lang.reflect.Constructor object to find the annotations on.
0435:             * @return an array with the constructor annotations
0436:             */
0437:            public Annotation[] getAnnotations(final Constructor constructor) {
0438:                final AnnotationReader.MemberKey key = AnnotationReader.MemberKey
0439:                        .newConstructorKey(constructor);
0440:                Object map = m_constructorAnnotationElements.get(key);
0441:                if (map != null) {
0442:                    final Collection annotationNames = ((Map) map).keySet();
0443:                    if (annotationNames.isEmpty()) {
0444:                        return EMPTY_ANNOTATION_ARRAY;
0445:                    }
0446:                    final Annotation[] annotations = new Annotation[annotationNames
0447:                            .size()];
0448:                    int i = 0;
0449:                    for (Iterator iterator = annotationNames.iterator(); iterator
0450:                            .hasNext();) {
0451:                        String annotationName = (String) iterator.next();
0452:                        annotations[i++] = getAnnotation(annotationName,
0453:                                constructor);
0454:                    }
0455:                    return annotations;
0456:                } else {
0457:                    return EMPTY_ANNOTATION_ARRAY;
0458:                }
0459:            }
0460:
0461:            /**
0462:             * Checks if an annotation is present at a specific method.
0463:             *
0464:             * @param annotationName the annotation name
0465:             * @param method         the java.lang.reflect.Method object to find the annotations on.
0466:             * @return true if the annotation is present else false
0467:             */
0468:            public boolean isAnnotationPresent(final String annotationName,
0469:                    final Method method) {
0470:                final AnnotationReader.MemberKey key = AnnotationReader.MemberKey
0471:                        .newMethodKey(method);
0472:                Object map = m_methodAnnotationElements.get(key);
0473:                if (map != null) {
0474:                    if (((Map) m_methodAnnotationElements.get(key))
0475:                            .containsKey(annotationName)) {
0476:                        return true;
0477:                    }
0478:                }
0479:                return false;
0480:            }
0481:
0482:            /**
0483:             * Returns the method annotation with the name specified for the method specified.
0484:             *
0485:             * @param annotationName the annotation name
0486:             * @param method         the java.lang.reflect.Method object to find the annotations on.
0487:             * @return the method annotation
0488:             */
0489:            public Annotation getAnnotation(final String annotationName,
0490:                    final Method method) {
0491:                return getMethodAnnotation(annotationName, MemberKey
0492:                        .newMethodKey(method), method.getDeclaringClass()
0493:                        .getClassLoader());
0494:            }
0495:
0496:            /**
0497:             * Returns the method annotation with the name specified for the method specified.
0498:             *
0499:             * @param annotationName
0500:             * @param methodName
0501:             * @param methodDesc
0502:             * @param loader
0503:             * @return
0504:             */
0505:            public Annotation getMethodAnnotation(final String annotationName,
0506:                    final String methodName, final String methodDesc,
0507:                    final ClassLoader loader) {
0508:                return getMethodAnnotation(annotationName, MemberKey
0509:                        .newMethodKey(methodName, methodDesc), loader);
0510:            }
0511:
0512:            /**
0513:             * Returns the method annotation with the name specified for the method specified.
0514:             *
0515:             * @param annotationName
0516:             * @param methodKey
0517:             * @param loader
0518:             * @return
0519:             */
0520:            private Annotation getMethodAnnotation(final String annotationName,
0521:                    final MemberKey methodKey, final ClassLoader loader) {
0522:                Map annotationMap = getMethodAnnotationCacheFor(methodKey);
0523:                Object cachedAnnotation = annotationMap.get(annotationName);
0524:                if (cachedAnnotation != null) {
0525:                    return (Annotation) cachedAnnotation;
0526:                }
0527:                // not in cache - create a new DP and put in cache
0528:                final Map annotations = (Map) m_methodAnnotationElements
0529:                        .get(methodKey);
0530:                if (annotations == null) {
0531:                    // no such annotation
0532:                    return null;
0533:                }
0534:                Object annotationElement = annotations.get(annotationName);
0535:                if (annotationElement != null) {
0536:                    Annotation annotation = ProxyFactory.newAnnotationProxy(
0537:                            (AnnotationElement.Annotation) annotationElement,
0538:                            loader);
0539:                    annotationMap.put(annotationName, annotation);
0540:                    return annotation;
0541:                }
0542:                return null;
0543:            }
0544:
0545:            /**
0546:             * Returns all the method annotations.
0547:             *
0548:             * @param method the java.lang.reflect.Method object to find the annotations on.
0549:             * @return an array with the method annotations
0550:             */
0551:            public Annotation[] getAnnotations(final Method method) {
0552:                final AnnotationReader.MemberKey key = AnnotationReader.MemberKey
0553:                        .newMethodKey(method);
0554:                Object map = m_methodAnnotationElements.get(key);
0555:                if (map != null) {
0556:                    final Collection annotationNames = ((Map) map).keySet();
0557:                    if (annotationNames.isEmpty()) {
0558:                        return EMPTY_ANNOTATION_ARRAY;
0559:                    }
0560:                    final Annotation[] annotations = new Annotation[annotationNames
0561:                            .size()];
0562:                    int i = 0;
0563:                    for (Iterator iterator = annotationNames.iterator(); iterator
0564:                            .hasNext();) {
0565:                        String annotationName = (String) iterator.next();
0566:                        annotations[i++] = getAnnotation(annotationName, method);
0567:                    }
0568:                    return annotations;
0569:                } else {
0570:                    return EMPTY_ANNOTATION_ARRAY;
0571:                }
0572:            }
0573:
0574:            /**
0575:             * Checks if an annotation is present at a specific field.
0576:             *
0577:             * @param annotationName the annotation name
0578:             * @param field          the java.lang.reflect.Field object to find the annotations on.
0579:             * @return true if the annotation is present else false
0580:             */
0581:            public boolean isAnnotationPresent(final String annotationName,
0582:                    final Field field) {
0583:                final AnnotationReader.MemberKey key = AnnotationReader.MemberKey
0584:                        .newFieldKey(field);
0585:                Object map = m_fieldAnnotationElements.get(key);
0586:                if (map != null) {
0587:                    if (((Map) map).containsKey(annotationName)) {
0588:                        return true;
0589:                    }
0590:                }
0591:                return false;
0592:            }
0593:
0594:            /**
0595:             * Returns the field annotation with the name specified for the field specified.
0596:             *
0597:             * @param annotationName the annotation name
0598:             * @param field          the java.lang.reflect.Field object to find the annotations on.
0599:             * @return the field annotation
0600:             */
0601:            public Annotation getAnnotation(final String annotationName,
0602:                    final Field field) {
0603:                return getFieldAnnotation(annotationName, MemberKey
0604:                        .newFieldKey(field), field.getDeclaringClass()
0605:                        .getClassLoader());
0606:            }
0607:
0608:            /**
0609:             * Returns the field annotation with the name specified for the field specified.
0610:             *
0611:             * @param annotationName
0612:             * @param fieldName
0613:             * @param fieldDesc
0614:             * @param loader
0615:             * @return
0616:             */
0617:            public Annotation getFieldAnnotation(final String annotationName,
0618:                    final String fieldName, final String fieldDesc,
0619:                    final ClassLoader loader) {
0620:                return getFieldAnnotation(annotationName, MemberKey
0621:                        .newFieldKey(fieldName, fieldDesc), loader);
0622:            }
0623:
0624:            /**
0625:             * Returns the field annotation with the name specified for the field specified.
0626:             *
0627:             * @param annotationName
0628:             * @param fieldKey
0629:             * @param loader
0630:             * @return
0631:             */
0632:            private Annotation getFieldAnnotation(final String annotationName,
0633:                    final MemberKey fieldKey, final ClassLoader loader) {
0634:                Map annotationMap = getFieldAnnotationCacheFor(fieldKey);
0635:                Object cachedAnnotation = annotationMap.get(annotationName);
0636:                if (cachedAnnotation != null) {
0637:                    return (Annotation) cachedAnnotation;
0638:                }
0639:                // not in cache - create a new DP and put in cache
0640:                final Map annotations = (Map) m_fieldAnnotationElements
0641:                        .get(fieldKey);
0642:                if (annotations == null) {
0643:                    // no such annotation
0644:                    return null;
0645:                }
0646:                Object annotationElement = annotations.get(annotationName);
0647:                if (annotationElement != null) {
0648:                    Annotation annotation = ProxyFactory.newAnnotationProxy(
0649:                            (AnnotationElement.Annotation) annotationElement,
0650:                            loader);
0651:                    annotationMap.put(annotationName, annotation);
0652:                    return annotation;
0653:                }
0654:                return null;
0655:            }
0656:
0657:            /**
0658:             * Returns all the field annotations.
0659:             *
0660:             * @param field the java.lang.reflect.Field object to find the annotations on.
0661:             * @return an array with the field annotations
0662:             */
0663:            public Annotation[] getAnnotations(final Field field) {
0664:                final AnnotationReader.MemberKey key = AnnotationReader.MemberKey
0665:                        .newFieldKey(field);
0666:                Object map = m_fieldAnnotationElements.get(key);
0667:                if (map != null) {
0668:                    final Collection annotationNames = ((Map) map).keySet();
0669:                    if (annotationNames.isEmpty()) {
0670:                        return EMPTY_ANNOTATION_ARRAY;
0671:                    }
0672:                    final Annotation[] annotations = new Annotation[annotationNames
0673:                            .size()];
0674:                    int i = 0;
0675:                    for (Iterator iterator = annotationNames.iterator(); iterator
0676:                            .hasNext();) {
0677:                        String annotationName = (String) iterator.next();
0678:                        annotations[i++] = getAnnotation(annotationName, field);
0679:                    }
0680:                    return annotations;
0681:                } else {
0682:                    return EMPTY_ANNOTATION_ARRAY;
0683:                }
0684:            }
0685:
0686:            /**
0687:             * Returns the class annotation element with the name specified.
0688:             *
0689:             * @param annotationName
0690:             * @return the class annotation
0691:             */
0692:            public AnnotationElement.Annotation getAnnotationElement(
0693:                    final String annotationName) {
0694:                return (AnnotationElement.Annotation) m_classAnnotationElements
0695:                        .get(annotationName);
0696:            }
0697:
0698:            /**
0699:             * Returns all the class annotations.
0700:             *
0701:             * @return an array with the class annotations
0702:             */
0703:            public AnnotationElement.Annotation[] getAnnotationElements() {
0704:                final Collection annotations = m_classAnnotationElements
0705:                        .values();
0706:                if (annotations.isEmpty()) {
0707:                    return EMPTY_ANNOTATION_ELEMENT_ARRAY;
0708:                }
0709:                return createAnnotationElementArray(annotations);
0710:            }
0711:
0712:            /**
0713:             * Checks if an annotation is present at a specific constructor.
0714:             *
0715:             * @param annotationName the annotation name
0716:             * @param desc           the constructor desc
0717:             * @return true if the annotation is present else false
0718:             */
0719:            public boolean isConstructorAnnotationPresent(
0720:                    final String annotationName, final String desc) {
0721:                final AnnotationReader.MemberKey key = AnnotationReader.MemberKey
0722:                        .newConstructorKey(desc);
0723:                Object map = m_constructorAnnotationElements.get(key);
0724:                if (map != null) {
0725:                    if (((Map) map).containsKey(annotationName)) {
0726:                        return true;
0727:                    }
0728:                }
0729:                return false;
0730:            }
0731:
0732:            /**
0733:             * Returns the annotation with the name specified for the constructor specified.
0734:             *
0735:             * @param annotationName the annotation name
0736:             * @param desc           the constructor desc
0737:             * @return the constructor annotation element
0738:             */
0739:            public AnnotationElement.Annotation getConstructorAnnotationElement(
0740:                    final String annotationName, final String desc) {
0741:                final AnnotationReader.MemberKey key = AnnotationReader.MemberKey
0742:                        .newConstructorKey(desc);
0743:                final Map annotations = (Map) m_constructorAnnotationElements
0744:                        .get(key);
0745:                if (annotations == null) {
0746:                    // no such annotation
0747:                    return null;
0748:                }
0749:                return (AnnotationElement.Annotation) annotations
0750:                        .get(annotationName);
0751:            }
0752:
0753:            /**
0754:             * Returns all the constructor annotation elements.
0755:             *
0756:             * @param desc the constructor desc
0757:             * @return an array with the constructor annotation elements
0758:             */
0759:            public AnnotationElement.Annotation[] getConstructorAnnotationElements(
0760:                    final String desc) {
0761:                final AnnotationReader.MemberKey key = AnnotationReader.MemberKey
0762:                        .newConstructorKey(desc);
0763:                Object map = m_constructorAnnotationElements.get(key);
0764:                if (map != null) {
0765:                    final Collection annotations = ((Map) map).values();
0766:                    if (annotations.isEmpty()) {
0767:                        return EMPTY_ANNOTATION_ELEMENT_ARRAY;
0768:                    }
0769:                    return createAnnotationElementArray(annotations);
0770:                } else {
0771:                    return EMPTY_ANNOTATION_ELEMENT_ARRAY;
0772:                }
0773:            }
0774:
0775:            /**
0776:             * Checks if an annotation is present at a specific method.
0777:             *
0778:             * @param annotationName the annotation name
0779:             * @param name           the method name
0780:             * @param desc           the method desc
0781:             * @return true if the annotation is present else false
0782:             */
0783:            public boolean isMethodAnnotationPresent(
0784:                    final String annotationName, final String name,
0785:                    final String desc) {
0786:                final AnnotationReader.MemberKey key = AnnotationReader.MemberKey
0787:                        .newMethodKey(name, desc);
0788:                Object map = m_methodAnnotationElements.get(key);
0789:                if (map != null) {
0790:                    if (((Map) map).containsKey(annotationName)) {
0791:                        return true;
0792:                    }
0793:                }
0794:                return false;
0795:            }
0796:
0797:            /**
0798:             * Returns the method annotation with the name specified for the method specified.
0799:             *
0800:             * @param annotationName the annotation name
0801:             * @param name           the method name
0802:             * @param desc           the method desc
0803:             * @return the method annotation element
0804:             */
0805:            public AnnotationElement.Annotation getMethodAnnotationElement(
0806:                    final String annotationName, final String name,
0807:                    final String desc) {
0808:                final AnnotationReader.MemberKey key = AnnotationReader.MemberKey
0809:                        .newMethodKey(name, desc);
0810:                final Map annotations = (Map) m_methodAnnotationElements
0811:                        .get(key);
0812:                if (annotations == null) {
0813:                    // no such annotation
0814:                    return null;
0815:                }
0816:                return (AnnotationElement.Annotation) annotations
0817:                        .get(annotationName);
0818:            }
0819:
0820:            /**
0821:             * Returns all the method annotation elements.
0822:             *
0823:             * @param name the method name
0824:             * @param desc the method desc
0825:             * @return an array with the method annotation elements
0826:             */
0827:            public AnnotationElement.Annotation[] getMethodAnnotationElements(
0828:                    final String name, final String desc) {
0829:                final AnnotationReader.MemberKey key = AnnotationReader.MemberKey
0830:                        .newMethodKey(name, desc);
0831:                Object map = m_methodAnnotationElements.get(key);
0832:                if (map != null) {
0833:                    final Collection annotations = ((Map) m_methodAnnotationElements
0834:                            .get(key)).values();
0835:                    if (annotations.isEmpty()) {
0836:                        return EMPTY_ANNOTATION_ELEMENT_ARRAY;
0837:                    }
0838:                    return createAnnotationElementArray(annotations);
0839:                } else {
0840:                    return EMPTY_ANNOTATION_ELEMENT_ARRAY;
0841:                }
0842:            }
0843:
0844:            /**
0845:             * Checks if an annotation is present at a specific field.
0846:             *
0847:             * @param annotationName the annotation name
0848:             * @param name           the field name
0849:             * @param desc           the field desc
0850:             * @return true if the annotation is present else false
0851:             */
0852:            public boolean isFieldAnnotationPresent(
0853:                    final String annotationName, final String name,
0854:                    final String desc) {
0855:                final AnnotationReader.MemberKey key = AnnotationReader.MemberKey
0856:                        .newFieldKey(name, desc);
0857:                Object map = m_fieldAnnotationElements.get(key);
0858:                if (map != null) {
0859:                    if (((Map) map).containsKey(annotationName)) {
0860:                        return true;
0861:                    }
0862:                }
0863:                return false;
0864:            }
0865:
0866:            /**
0867:             * Returns the annotation with the name specified for the field specified.
0868:             *
0869:             * @param annotationName the annotation name
0870:             * @param name           the field name
0871:             * @param desc           the field desc
0872:             * @return the field annotation element
0873:             */
0874:            public AnnotationElement.Annotation getFieldAnnotationElement(
0875:                    final String annotationName, final String name,
0876:                    final String desc) {
0877:                final AnnotationReader.MemberKey key = AnnotationReader.MemberKey
0878:                        .newFieldKey(name, desc);
0879:                final Map annotations = (Map) m_fieldAnnotationElements
0880:                        .get(key);
0881:                if (annotations == null) {
0882:                    // no such annotation
0883:                    return null;
0884:                }
0885:                return (AnnotationElement.Annotation) annotations
0886:                        .get(annotationName);
0887:            }
0888:
0889:            /**
0890:             * Returns all the field annotation elements.
0891:             *
0892:             * @param name the field name
0893:             * @param desc the field desc
0894:             * @return an array with the field annotation elements
0895:             */
0896:            public AnnotationElement.Annotation[] getFieldAnnotationElements(
0897:                    final String name, final String desc) {
0898:                final AnnotationReader.MemberKey key = AnnotationReader.MemberKey
0899:                        .newFieldKey(name, desc);
0900:                Object map = m_fieldAnnotationElements.get(key);
0901:                if (map != null) {
0902:                    final Collection annotations = ((Map) m_fieldAnnotationElements
0903:                            .get(key)).values();
0904:                    if (annotations.isEmpty()) {
0905:                        return EMPTY_ANNOTATION_ELEMENT_ARRAY;
0906:                    }
0907:                    return createAnnotationElementArray(annotations);
0908:                } else {
0909:                    return EMPTY_ANNOTATION_ELEMENT_ARRAY;
0910:                }
0911:            }
0912:
0913:            /**
0914:             * Creates an annotation element array.
0915:             *
0916:             * @param annotations the collection with elements
0917:             * @return the array
0918:             */
0919:            private AnnotationElement.Annotation[] createAnnotationElementArray(
0920:                    final Collection annotations) {
0921:                int i = 0;
0922:                final AnnotationElement.Annotation[] elementArray = new AnnotationElement.Annotation[annotations
0923:                        .size()];
0924:                for (Iterator it = annotations.iterator(); it.hasNext();) {
0925:                    elementArray[i++] = (AnnotationElement.Annotation) it
0926:                            .next();
0927:                }
0928:                return elementArray;
0929:            }
0930:
0931:            /**
0932:             * Returns the annotation cache for a specific constructor.
0933:             *
0934:             * @param constructor the constructor
0935:             * @return the cache
0936:             */
0937:            private Map getConstructorAnnotationCacheFor(
0938:                    final MemberKey constructor) {
0939:                Map annotationMap = (Map) m_constructorAnnotationCache
0940:                        .get(constructor);
0941:                if (annotationMap == null) {
0942:                    annotationMap = new HashMap();
0943:                    m_constructorAnnotationCache
0944:                            .put(constructor, annotationMap);
0945:                }
0946:                return annotationMap;
0947:            }
0948:
0949:            /**
0950:             * Returns the annotation cache for a specific method.
0951:             *
0952:             * @param method the method
0953:             * @return the cache
0954:             */
0955:            private Map getMethodAnnotationCacheFor(final MemberKey method) {
0956:                Map annotationMap = (Map) m_methodAnnotationCache.get(method);
0957:                if (annotationMap == null) {
0958:                    annotationMap = new HashMap();
0959:                    m_methodAnnotationCache.put(method, annotationMap);
0960:                }
0961:                return annotationMap;
0962:            }
0963:
0964:            /**
0965:             * Returns the annotation cache for a specific field.
0966:             *
0967:             * @param field the field
0968:             * @return the cache
0969:             */
0970:            private Map getFieldAnnotationCacheFor(final MemberKey field) {
0971:                Map annotationMap = (Map) m_fieldAnnotationCache.get(field);
0972:                if (annotationMap == null) {
0973:                    annotationMap = new HashMap();
0974:                    m_fieldAnnotationCache.put(field, annotationMap);
0975:                }
0976:                return annotationMap;
0977:            }
0978:
0979:            /**
0980:             * Resets the annotation reader and triggers a new parsing of the newly read bytecode.
0981:             * <p/>
0982:             * This method calls <code>parse</code> and is therefore all the is needed to invoke to get a fully updated reader.
0983:             */
0984:            private void refresh() {
0985:                m_classAnnotationElements.clear();
0986:                m_constructorAnnotationElements.clear();
0987:                m_methodAnnotationElements.clear();
0988:                m_fieldAnnotationElements.clear();
0989:                m_classAnnotationCache.clear();
0990:                m_constructorAnnotationCache.clear();
0991:                m_methodAnnotationCache.clear();
0992:                m_fieldAnnotationCache.clear();
0993:                AnnotationDefaults.refresh(m_classKey);
0994:                parse(m_classKey);
0995:            }
0996:
0997:            /**
0998:             * Parses the class bytecode and retrieves the annotations.
0999:             *
1000:             * @param classKey
1001:             */
1002:            private void parse(final ClassKey classKey) {
1003:                final String className = classKey.getName();
1004:                final ClassLoader loader = classKey.getClassLoader();
1005:                final byte[] bytes;
1006:                try {
1007:                    bytes = getBytecodeFor(className, loader);
1008:                } catch (Exception e) {
1009:                    // e.printStackTrace();
1010:                    System.err.println("[WARN] " + e.getMessage());
1011:                    return;
1012:                    //            throw new ReaderException(
1013:                    //                    "could not retrieve the bytecode for class [" + className + "]", e
1014:                    //            );
1015:                }
1016:                ClassReader classReader = new ClassReader(bytes);
1017:                classReader.accept(new AnnotationRetrievingVisitor(),
1018:                        ClassReader.SKIP_DEBUG | ClassReader.SKIP_CODE
1019:                                | ClassReader.SKIP_FRAMES);
1020:            }
1021:
1022:            /**
1023:             * Creates a new instance of the annotation reader, reads from the class specified.
1024:             *
1025:             * @param classKey
1026:             */
1027:            private AnnotationReader(final ClassKey classKey) {
1028:                if (classKey == null) {
1029:                    throw new IllegalArgumentException(
1030:                            "class info can not be null");
1031:                }
1032:                m_classKey = classKey;
1033:                parse(classKey);
1034:            }
1035:
1036:            /**
1037:             * Retrieves the Java 5 RuntimeVisibleAnnotations annotations from the class bytecode.
1038:             */
1039:            class AnnotationRetrievingVisitor extends EmptyVisitor {
1040:
1041:                public AnnotationVisitor visitAnnotation(final String desc,
1042:                        final boolean visible) {
1043:                    String annotationClassName = toJavaName(desc);
1044:                    final AnnotationElement.Annotation annotation = new AnnotationElement.Annotation(
1045:                            annotationClassName);
1046:                    m_classAnnotationElements.put(annotationClassName,
1047:                            annotation);
1048:                    return createAnnotationVisitor(annotation);
1049:                }
1050:
1051:                public FieldVisitor visitField(final int access,
1052:                        final String name, final String desc,
1053:                        final String signature, final Object value) {
1054:                    final MemberKey key = new MemberKey(name, desc);
1055:                    return new AnnotationRetrievingFieldVisitor(key,
1056:                            AnnotationReader.this );
1057:                }
1058:
1059:                public MethodVisitor visitMethod(final int access,
1060:                        final String name, final String desc,
1061:                        final String signature, final String[] exceptions) {
1062:                    final MemberKey key = new MemberKey(name, desc);
1063:                    if (name.equals(INIT_METHOD_NAME)) {
1064:                        return new AnnotationRetrievingConstructorVisitor(key,
1065:                                AnnotationReader.this );
1066:                    } else {
1067:                        return new AnnotationRetrievingMethodVisitor(key,
1068:                                AnnotationReader.this );
1069:                    }
1070:                }
1071:
1072:            }
1073:
1074:            /**
1075:             * Returns the annotation visitor to use.
1076:             * <p/>
1077:             * Swap to the 'tracing' visitor for simple debugging.
1078:             *
1079:             * @param annotation
1080:             * @return
1081:             */
1082:            public AnnotationVisitor createAnnotationVisitor(
1083:                    final AnnotationElement.Annotation annotation) {
1084:                return new AnnotationBuilderVisitor(annotation, m_classKey
1085:                        .getClassLoader(), annotation.getInterfaceName());
1086:                //            return new TraceAnnotationVisitor();
1087:            }
1088:
1089:            static final class AnnotationRetrievingConstructorVisitor extends
1090:                    EmptyVisitor {
1091:                private final MemberKey key;
1092:                private final AnnotationReader reader;
1093:
1094:                AnnotationRetrievingConstructorVisitor(MemberKey key,
1095:                        AnnotationReader reader) {
1096:                    this .key = key;
1097:                    this .reader = reader;
1098:                }
1099:
1100:                public AnnotationVisitor visitAnnotation(final String desc,
1101:                        final boolean visible) {
1102:                    final String className = toJavaName(desc);
1103:                    final AnnotationElement.Annotation annotation = new AnnotationElement.Annotation(
1104:                            className);
1105:                    if (reader.m_constructorAnnotationElements.containsKey(key)) {
1106:                        ((Map) reader.m_constructorAnnotationElements.get(key))
1107:                                .put(className, annotation);
1108:                    } else {
1109:                        final Map annotations = new HashMap();
1110:                        annotations.put(className, annotation);
1111:                        reader.m_constructorAnnotationElements.put(key,
1112:                                annotations);
1113:                    }
1114:                    return reader.createAnnotationVisitor(annotation);
1115:                }
1116:            }
1117:
1118:            static final class AnnotationRetrievingMethodVisitor extends
1119:                    EmptyVisitor {
1120:                private final MemberKey key;
1121:                private final AnnotationReader reader;
1122:
1123:                AnnotationRetrievingMethodVisitor(MemberKey key,
1124:                        AnnotationReader reader) {
1125:                    this .key = key;
1126:                    this .reader = reader;
1127:                }
1128:
1129:                public AnnotationVisitor visitAnnotation(final String desc,
1130:                        final boolean visible) {
1131:                    String className = toJavaName(desc);
1132:                    final AnnotationElement.Annotation annotation = new AnnotationElement.Annotation(
1133:                            className);
1134:                    if (reader.m_methodAnnotationElements.containsKey(key)) {
1135:                        ((Map) reader.m_methodAnnotationElements.get(key)).put(
1136:                                className, annotation);
1137:                    } else {
1138:                        final Map annotations = new HashMap();
1139:                        annotations.put(className, annotation);
1140:                        reader.m_methodAnnotationElements.put(key, annotations);
1141:                    }
1142:                    return reader.createAnnotationVisitor(annotation);
1143:                }
1144:            }
1145:
1146:            static final class AnnotationRetrievingFieldVisitor extends
1147:                    EmptyVisitor {
1148:                private final MemberKey key;
1149:                private final AnnotationReader reader;
1150:
1151:                AnnotationRetrievingFieldVisitor(MemberKey key,
1152:                        AnnotationReader reader) {
1153:                    this .key = key;
1154:                    this .reader = reader;
1155:                }
1156:
1157:                public AnnotationVisitor visitAnnotation(final String desc,
1158:                        boolean visible) {
1159:                    final String className = toJavaName(desc);
1160:                    final AnnotationElement.Annotation annotation = new AnnotationElement.Annotation(
1161:                            className);
1162:                    if (reader.m_fieldAnnotationElements.containsKey(key)) {
1163:                        ((Map) reader.m_fieldAnnotationElements.get(key)).put(
1164:                                className, annotation);
1165:                    } else {
1166:                        final Map annotations = new HashMap();
1167:                        annotations.put(className, annotation);
1168:                        reader.m_fieldAnnotationElements.put(key, annotations);
1169:                    }
1170:                    return reader.createAnnotationVisitor(annotation);
1171:                }
1172:
1173:            }
1174:
1175:            static class AnnotationBuilderVisitor implements  AnnotationVisitor {
1176:
1177:                private final AnnotationElement.NestedAnnotationElement m_nestedAnnotationElement;
1178:
1179:                /**
1180:                 * ClassLoader from which both the annotated element and its annoation(s) are visible
1181:                 */
1182:                private final ClassLoader m_loader;
1183:
1184:                /**
1185:                 * Annotation class name. If not null, default values will be handled, else it will be skip.
1186:                 * (f.e. skip for nested annotation and arrays)
1187:                 */
1188:                private final String m_annotationClassName;
1189:
1190:                public AnnotationBuilderVisitor(
1191:                        final AnnotationElement.NestedAnnotationElement annotation,
1192:                        final ClassLoader loader,
1193:                        final String annotationClassName) {
1194:                    m_nestedAnnotationElement = annotation;
1195:                    m_loader = loader;
1196:                    m_annotationClassName = annotationClassName;
1197:                }
1198:
1199:                public void visit(final String name, final Object value) {
1200:                    if (value instanceof  Type) {
1201:                        // type
1202:                        m_nestedAnnotationElement.addElement(name, value);
1203:                    } else {
1204:                        // primitive value
1205:                        if (value.getClass().isArray()) {
1206:                            // primitive array value
1207:                            handlePrimitiveArrayValue(value, name);
1208:                        } else {
1209:                            // primitive non-array value
1210:                            m_nestedAnnotationElement.addElement(name, value);
1211:                        }
1212:                    }
1213:                }
1214:
1215:                public void visitEnum(final String name, final String desc,
1216:                        final String value) {
1217:                    m_nestedAnnotationElement.addElement(name,
1218:                            new AnnotationElement.Enum(desc, value));
1219:                }
1220:
1221:                public AnnotationVisitor visitAnnotation(final String name,
1222:                        final String desc) {
1223:                    String className = toJavaName(desc);
1224:                    AnnotationElement.NestedAnnotationElement annotation = new AnnotationElement.Annotation(
1225:                            className);
1226:                    m_nestedAnnotationElement.addElement(name, annotation);
1227:                    return new AnnotationBuilderVisitor(annotation, m_loader,
1228:                            className);//recursive default handling
1229:                }
1230:
1231:                public AnnotationVisitor visitArray(final String name) {
1232:                    AnnotationElement.NestedAnnotationElement array = new AnnotationElement.Array();
1233:                    m_nestedAnnotationElement.addElement(name, array);
1234:                    return new AnnotationBuilderVisitor(array, m_loader, null);
1235:                }
1236:
1237:                public void visitEnd() {
1238:                    // annotation default overrides
1239:                    if (m_annotationClassName != null) {
1240:                        AnnotationElement.Annotation defaults = AnnotationDefaults
1241:                                .getDefaults(m_annotationClassName, m_loader);
1242:                        AnnotationElement.Annotation annotation = (AnnotationElement.Annotation) m_nestedAnnotationElement;
1243:                        for (Iterator iterator = defaults.getElements()
1244:                                .iterator(); iterator.hasNext();) {
1245:                            AnnotationElement.NamedValue defaultedElement = (AnnotationElement.NamedValue) iterator
1246:                                    .next();
1247:                            annotation.mergeDefaultedElement(defaultedElement);
1248:                        }
1249:                    }
1250:                }
1251:
1252:                /**
1253:                 * Handles array of primitive values. The JSR-175 spec. only suppots one dimensional arrays.
1254:                 *
1255:                 * @param value
1256:                 * @param name
1257:                 */
1258:                private void handlePrimitiveArrayValue(final Object value,
1259:                        final String name) {
1260:                    if (value.getClass().getComponentType().isPrimitive()) {
1261:                        // primitive array type
1262:                        if (value instanceof  String[]) {
1263:                            // string array
1264:                            m_nestedAnnotationElement.addElement(name, value);
1265:                        } else {
1266:                            AnnotationElement.NestedAnnotationElement arrayElement = new AnnotationElement.Array();
1267:                            // non-string primitive array
1268:                            if (value instanceof  int[]) {
1269:                                int[] array = (int[]) value;
1270:                                for (int i = 0; i < array.length; i++) {
1271:                                    arrayElement.addElement(null, new Integer(
1272:                                            array[i]));
1273:                                }
1274:                            } else if (value instanceof  long[]) {
1275:                                long[] array = (long[]) value;
1276:                                for (int i = 0; i < array.length; i++) {
1277:                                    arrayElement.addElement(null, new Long(
1278:                                            array[i]));
1279:                                }
1280:                            } else if (value instanceof  short[]) {
1281:                                short[] array = (short[]) value;
1282:                                for (int i = 0; i < array.length; i++) {
1283:                                    arrayElement.addElement(null, new Short(
1284:                                            array[i]));
1285:                                }
1286:                            } else if (value instanceof  float[]) {
1287:                                float[] array = (float[]) value;
1288:                                for (int i = 0; i < array.length; i++) {
1289:                                    arrayElement.addElement(null, new Float(
1290:                                            array[i]));
1291:                                }
1292:                            } else if (value instanceof  double[]) {
1293:                                double[] array = (double[]) value;
1294:                                for (int i = 0; i < array.length; i++) {
1295:                                    arrayElement.addElement(null, new Double(
1296:                                            array[i]));
1297:                                }
1298:                            } else if (value instanceof  boolean[]) {
1299:                                boolean[] array = (boolean[]) value;
1300:                                for (int i = 0; i < array.length; i++) {
1301:                                    arrayElement.addElement(null, new Boolean(
1302:                                            array[i]));
1303:                                }
1304:                            } else if (value instanceof  byte[]) {
1305:                                byte[] array = (byte[]) value;
1306:                                for (int i = 0; i < array.length; i++) {
1307:                                    arrayElement.addElement(null, new Byte(
1308:                                            array[i]));
1309:                                }
1310:                            } else if (value instanceof  char[]) {
1311:                                char[] array = (char[]) value;
1312:                                for (int i = 0; i < array.length; i++) {
1313:                                    arrayElement.addElement(null,
1314:                                            new Character(array[i]));
1315:                                }
1316:                            }
1317:                            m_nestedAnnotationElement.addElement(name,
1318:                                    arrayElement);
1319:                        }
1320:                    } else {
1321:                        m_nestedAnnotationElement.addElement(name, value);
1322:                    }
1323:                }
1324:            }
1325:
1326:            /**
1327:             * Contains info about the class being parsed. Holds the class name and a weak ref to the class loader. Also works
1328:             * as a unique key. Needed since at bytecode parsing time we do not have access to the reflect members, only
1329:             * strings.
1330:             *
1331:             * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér</a>
1332:             */
1333:            public static class ClassKey {
1334:                private final String m_name;
1335:                private final WeakReference m_loaderRef;
1336:
1337:                public ClassKey(final String name, final ClassLoader loader) {
1338:                    m_name = name.replace('.', '/');
1339:                    m_loaderRef = new WeakReference(loader);
1340:                }
1341:
1342:                public String getName() {
1343:                    return m_name;
1344:                }
1345:
1346:                public ClassLoader getClassLoader() {
1347:                    return (ClassLoader) m_loaderRef.get();
1348:                }
1349:
1350:                public boolean equals(Object o) {
1351:                    if (this  == o) {
1352:                        return true;
1353:                    }
1354:                    if (!(o instanceof  ClassKey)) {
1355:                        return false;
1356:                    }
1357:                    final ClassKey classKey = (ClassKey) o;
1358:                    ClassLoader loader1 = (ClassLoader) m_loaderRef.get();
1359:                    ClassLoader loader2 = (ClassLoader) classKey.m_loaderRef
1360:                            .get();
1361:                    if (loader1 != null ? !loader1.equals(loader2)
1362:                            : loader2 != null) {
1363:                        return false;
1364:                    }
1365:                    if (m_name != null ? !m_name.equals(classKey.m_name)
1366:                            : classKey.m_name != null) {
1367:                        return false;
1368:                    }
1369:                    return true;
1370:                }
1371:
1372:                public int hashCode() {
1373:                    int result;
1374:                    result = (m_name != null ? m_name.hashCode() : 0);
1375:                    ClassLoader loader = (ClassLoader) m_loaderRef.get();
1376:                    result = 29 * result
1377:                            + (loader != null ? loader.hashCode() : 0);
1378:                    return result;
1379:                }
1380:            }
1381:
1382:            /**
1383:             * Unique key for class members (methods, fields and constructors) to be used in hash maps etc.
1384:             * <p/>
1385:             * Needed since at bytecode parsing time we do not have access to the reflect members, only strings.
1386:             *
1387:             * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér</a>
1388:             */
1389:            public static class MemberKey {
1390:                private final String m_name;
1391:                private final String m_desc;
1392:
1393:                public static MemberKey newConstructorKey(
1394:                        final Constructor method) {
1395:                    return new MemberKey(INIT_METHOD_NAME, SignatureHelper
1396:                            .getConstructorSignature(method));
1397:                }
1398:
1399:                public static MemberKey newConstructorKey(final String desc) {
1400:                    return new MemberKey(INIT_METHOD_NAME, desc);
1401:                }
1402:
1403:                public static MemberKey newMethodKey(final Method method) {
1404:                    return new MemberKey(method.getName(), SignatureHelper
1405:                            .getMethodSignature(method));
1406:                }
1407:
1408:                public static MemberKey newMethodKey(final String name,
1409:                        final String desc) {
1410:                    return new MemberKey(name, desc);
1411:                }
1412:
1413:                public static MemberKey newFieldKey(final Field field) {
1414:                    return new MemberKey(field.getName(), SignatureHelper
1415:                            .getFieldSignature(field));
1416:                }
1417:
1418:                public static MemberKey newFieldKey(final String name,
1419:                        final String desc) {
1420:                    return new MemberKey(name, desc);
1421:                }
1422:
1423:                public MemberKey(final String name, final String desc) {
1424:                    m_name = name;
1425:                    m_desc = desc;
1426:                }
1427:
1428:                public boolean equals(Object o) {
1429:                    if (this  == o) {
1430:                        return true;
1431:                    }
1432:                    if (!(o instanceof  MemberKey)) {
1433:                        return false;
1434:                    }
1435:                    final MemberKey memberKey = (MemberKey) o;
1436:                    if (m_desc != null ? !m_desc.equals(memberKey.m_desc)
1437:                            : memberKey.m_desc != null) {
1438:                        return false;
1439:                    }
1440:                    if (m_name != null ? !m_name.equals(memberKey.m_name)
1441:                            : memberKey.m_name != null) {
1442:                        return false;
1443:                    }
1444:                    return true;
1445:                }
1446:
1447:                public int hashCode() {
1448:                    int result;
1449:                    result = (m_name != null ? m_name.hashCode() : 0);
1450:                    result = 29 * result
1451:                            + (m_desc != null ? m_desc.hashCode() : 0);
1452:                    return result;
1453:                }
1454:            }
1455:
1456:            /**
1457:             * To be used for debugging purposes.
1458:             */
1459:            private class TraceAnnotationVisitor implements  AnnotationVisitor {
1460:                public void visit(final String name, final Object value) {
1461:                    System.out.println("    NAMED-VALUE: " + name + "->"
1462:                            + value);
1463:                }
1464:
1465:                public void visitEnum(final String name, final String desc,
1466:                        final String value) {
1467:                    System.out.println("    ENUM: " + name);
1468:                }
1469:
1470:                public AnnotationVisitor visitAnnotation(final String name,
1471:                        final String desc) {
1472:                    System.out.println("    ANNOTATION: " + name);
1473:                    return new TraceAnnotationVisitor();
1474:                }
1475:
1476:                public AnnotationVisitor visitArray(final String name) {
1477:                    System.out.println("    ARRAY: " + name);
1478:                    return new TraceAnnotationVisitor();
1479:                }
1480:
1481:                public void visitEnd() {
1482:                }
1483:            }
1484:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.