1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.annotations;
20
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.net.URI;
24 import java.net.URL;
25 import java.net.URLClassLoader;
26 import java.util.ArrayList;
27 import java.util.Arrays;
28 import java.util.HashSet;
29 import java.util.List;
30 import java.util.Locale;
31 import java.util.Set;
32 import java.util.jar.JarEntry;
33
34 import org.eclipse.jetty.util.Loader;
35 import org.eclipse.jetty.util.log.Log;
36 import org.eclipse.jetty.util.log.Logger;
37 import org.eclipse.jetty.util.resource.Resource;
38 import org.eclipse.jetty.webapp.JarScanner;
39 import org.objectweb.asm.AnnotationVisitor;
40 import org.objectweb.asm.ClassReader;
41 import org.objectweb.asm.FieldVisitor;
42 import org.objectweb.asm.MethodVisitor;
43 import org.objectweb.asm.commons.EmptyVisitor;
44
45
46
47
48
49
50
51 public class AnnotationParser
52 {
53 private static final Logger LOG = Log.getLogger(AnnotationParser.class);
54
55 protected Set<String> _parsedClassNames = new HashSet<String>();
56 protected List<Handler> _handlers = new ArrayList<Handler>();
57
58 public static String normalize (String name)
59 {
60 if (name==null)
61 return null;
62
63 if (name.startsWith("L") && name.endsWith(";"))
64 name = name.substring(1, name.length()-1);
65
66 if (name.endsWith(".class"))
67 name = name.substring(0, name.length()-".class".length());
68
69 return name.replace('/', '.');
70 }
71
72
73
74 public abstract class Value
75 {
76 String _name;
77
78 public Value (String name)
79 {
80 _name = name;
81 }
82
83 public String getName()
84 {
85 return _name;
86 }
87
88 public abstract Object getValue();
89
90 }
91
92
93
94
95 public class SimpleValue extends Value
96 {
97 Object _val;
98
99 public SimpleValue(String name)
100 {
101 super(name);
102 }
103
104 public void setValue(Object val)
105 {
106 _val=val;
107 }
108 @Override
109 public Object getValue()
110 {
111 return _val;
112 }
113
114 @Override
115 public String toString()
116 {
117 return "("+getName()+":"+_val+")";
118 }
119 }
120
121 public class ListValue extends Value
122 {
123 List<Value> _val;
124
125 public ListValue (String name)
126 {
127 super(name);
128 _val = new ArrayList<Value>();
129 }
130
131 @Override
132 public Object getValue()
133 {
134 return _val;
135 }
136
137 public List<Value> getList()
138 {
139 return _val;
140 }
141
142 public void addValue (Value v)
143 {
144 _val.add(v);
145 }
146
147 public int size ()
148 {
149 return _val.size();
150 }
151
152 @Override
153 public String toString()
154 {
155 StringBuffer buff = new StringBuffer();
156 buff.append("(");
157 buff.append(getName());
158 buff.append(":");
159 for (Value n: _val)
160 {
161 buff.append(" "+n.toString());
162 }
163 buff.append(")");
164
165 return buff.toString();
166 }
167 }
168
169
170
171
172
173
174
175
176 public interface Handler
177 {
178
179 }
180
181
182
183
184
185
186
187
188 public interface DiscoverableAnnotationHandler extends Handler
189 {
190
191
192
193
194
195
196
197
198
199
200
201 public void handleClass (String className, int version, int access,
202 String signature, String superName, String[] interfaces,
203 String annotation, List<Value>values);
204
205
206
207
208
209
210
211
212
213
214
215
216 public void handleMethod (String className, String methodName, int access,
217 String desc, String signature,String[] exceptions,
218 String annotation, List<Value>values);
219
220
221
222
223
224
225
226
227
228
229
230
231
232 public void handleField (String className, String fieldName, int access,
233 String fieldType, String signature, Object value,
234 String annotation, List<Value>values);
235
236
237
238
239
240
241
242 public String getAnnotationName();
243 }
244
245
246
247
248
249
250
251
252 public interface ClassHandler extends Handler
253 {
254 public void handle (String className, int version, int access, String signature, String superName, String[] interfaces);
255 }
256
257
258
259
260
261
262
263
264 public interface MethodHandler extends Handler
265 {
266 public void handle (String className, String methodName, int access, String desc, String signature,String[] exceptions);
267 }
268
269
270
271
272
273
274
275 public interface FieldHandler extends Handler
276 {
277 public void handle (String className, String fieldName, int access, String fieldType, String signature, Object value);
278 }
279
280
281
282
283
284
285
286
287 public class MyAnnotationVisitor implements AnnotationVisitor
288 {
289 List<Value> _annotationValues;
290 String _annotationName;
291
292 public MyAnnotationVisitor (String annotationName, List<Value> values)
293 {
294 _annotationValues = values;
295 _annotationName = annotationName;
296 }
297
298 public List<Value> getAnnotationValues()
299 {
300 return _annotationValues;
301 }
302
303
304
305
306
307 @Override
308 public void visit(String aname, Object avalue)
309 {
310 SimpleValue v = new SimpleValue(aname);
311 v.setValue(avalue);
312 _annotationValues.add(v);
313 }
314
315
316
317
318
319 @Override
320 public AnnotationVisitor visitAnnotation(String name, String desc)
321 {
322 String s = normalize(desc);
323 ListValue v = new ListValue(s);
324 _annotationValues.add(v);
325 MyAnnotationVisitor visitor = new MyAnnotationVisitor(s, v.getList());
326 return visitor;
327 }
328
329
330
331
332
333 @Override
334 public AnnotationVisitor visitArray(String name)
335 {
336 ListValue v = new ListValue(name);
337 _annotationValues.add(v);
338 MyAnnotationVisitor visitor = new MyAnnotationVisitor(null, v.getList());
339 return visitor;
340 }
341
342
343
344
345
346 @Override
347 public void visitEnum(String name, String desc, String value)
348 {
349
350 }
351
352 @Override
353 public void visitEnd()
354 {
355 }
356 }
357
358
359
360
361
362
363
364
365
366 public class MyClassVisitor extends EmptyVisitor
367 {
368 String _className;
369 int _access;
370 String _signature;
371 String _superName;
372 String[] _interfaces;
373 int _version;
374
375
376 @Override
377 public void visit (int version,
378 final int access,
379 final String name,
380 final String signature,
381 final String superName,
382 final String[] interfaces)
383 {
384 _className = normalize(name);
385 _access = access;
386 _signature = signature;
387 _superName = superName;
388 _interfaces = interfaces;
389 _version = version;
390
391 _parsedClassNames.add(_className);
392
393 String[] normalizedInterfaces = null;
394 if (interfaces!= null)
395 {
396 normalizedInterfaces = new String[interfaces.length];
397 int i=0;
398 for (String s : interfaces)
399 normalizedInterfaces[i++] = normalize(s);
400 }
401
402 for (Handler h : AnnotationParser.this._handlers)
403 {
404 if (h instanceof ClassHandler)
405 {
406 ((ClassHandler)h).handle(_className, _version, _access, _signature, normalize(_superName), normalizedInterfaces);
407 }
408 }
409 }
410
411 @Override
412 public AnnotationVisitor visitAnnotation (String desc, boolean visible)
413 {
414 MyAnnotationVisitor visitor = new MyAnnotationVisitor(normalize(desc), new ArrayList<Value>())
415 {
416 @Override
417 public void visitEnd()
418 {
419 super.visitEnd();
420
421
422 for (Handler h : AnnotationParser.this._handlers)
423 {
424 if (h instanceof DiscoverableAnnotationHandler)
425 {
426 DiscoverableAnnotationHandler dah = (DiscoverableAnnotationHandler)h;
427 if (_annotationName.equalsIgnoreCase(dah.getAnnotationName()))
428 dah.handleClass(_className, _version, _access, _signature, _superName, _interfaces, _annotationName, _annotationValues);
429 }
430 }
431 }
432 };
433
434 return visitor;
435 }
436
437 @Override
438 public MethodVisitor visitMethod (final int access,
439 final String name,
440 final String methodDesc,
441 final String signature,
442 final String[] exceptions)
443 {
444
445 return new EmptyVisitor ()
446 {
447 @Override
448 public AnnotationVisitor visitAnnotation(String desc, boolean visible)
449 {
450 MyAnnotationVisitor visitor = new MyAnnotationVisitor (normalize(desc), new ArrayList<Value>())
451 {
452 @Override
453 public void visitEnd()
454 {
455 super.visitEnd();
456
457 for (Handler h : AnnotationParser.this._handlers)
458 {
459 if (h instanceof DiscoverableAnnotationHandler)
460 {
461 DiscoverableAnnotationHandler dah = (DiscoverableAnnotationHandler)h;
462 if (_annotationName.equalsIgnoreCase(dah.getAnnotationName()))
463 dah.handleMethod(_className, name, access, methodDesc, signature, exceptions, _annotationName, _annotationValues);
464 }
465 }
466 }
467 };
468
469 return visitor;
470 }
471 };
472 }
473
474 @Override
475 public FieldVisitor visitField (final int access,
476 final String fieldName,
477 final String fieldType,
478 final String signature,
479 final Object value)
480 {
481
482 return new EmptyVisitor ()
483 {
484 @Override
485 public AnnotationVisitor visitAnnotation(String desc, boolean visible)
486 {
487 MyAnnotationVisitor visitor = new MyAnnotationVisitor(normalize(desc), new ArrayList<Value>())
488 {
489 @Override
490 public void visitEnd()
491 {
492 super.visitEnd();
493 for (Handler h : AnnotationParser.this._handlers)
494 {
495 if (h instanceof DiscoverableAnnotationHandler)
496 {
497 DiscoverableAnnotationHandler dah = (DiscoverableAnnotationHandler)h;
498 if (_annotationName.equalsIgnoreCase(dah.getAnnotationName()))
499 dah.handleField(_className, fieldName, access, fieldType, signature, value, _annotationName, _annotationValues);
500 }
501 }
502 }
503 };
504 return visitor;
505 }
506 };
507 }
508 }
509
510
511
512
513
514
515
516
517
518
519 @Deprecated
520 public void registerAnnotationHandler (String annotationName, DiscoverableAnnotationHandler handler)
521 {
522 _handlers.add(handler);
523 }
524
525
526
527
528
529
530
531 @Deprecated
532 public List<DiscoverableAnnotationHandler> getAnnotationHandlers(String annotationName)
533 {
534 List<DiscoverableAnnotationHandler> handlers = new ArrayList<DiscoverableAnnotationHandler>();
535 for (Handler h:_handlers)
536 {
537 if (h instanceof DiscoverableAnnotationHandler)
538 {
539 DiscoverableAnnotationHandler dah = (DiscoverableAnnotationHandler)h;
540 if (annotationName.equals(dah.getAnnotationName()))
541 handlers.add(dah);
542 }
543 }
544
545 return handlers;
546 }
547
548
549
550
551
552 @Deprecated
553 public List<DiscoverableAnnotationHandler> getAnnotationHandlers()
554 {
555 List<DiscoverableAnnotationHandler> allAnnotationHandlers = new ArrayList<DiscoverableAnnotationHandler>();
556 for (Handler h:_handlers)
557 {
558 if (h instanceof DiscoverableAnnotationHandler)
559 allAnnotationHandlers.add((DiscoverableAnnotationHandler)h);
560 }
561 return allAnnotationHandlers;
562 }
563
564
565
566
567
568 @Deprecated
569 public void registerClassHandler (ClassHandler handler)
570 {
571 _handlers.add(handler);
572 }
573
574
575
576
577
578
579
580
581 public void registerHandler(Handler h)
582 {
583 if (h == null)
584 return;
585
586 _handlers.add(h);
587 }
588
589
590
591
592
593
594
595 public void registerHandlers(List<? extends Handler> handlers)
596 {
597 if (handlers == null)
598 return;
599 _handlers.addAll(handlers);
600 }
601
602
603
604
605
606
607
608
609 public boolean deregisterHandler(Handler h)
610 {
611 return _handlers.remove(h);
612 }
613
614
615
616
617
618 public void clearHandlers()
619 {
620 _handlers.clear();
621 }
622
623
624
625
626
627
628
629 public boolean isParsed (String className)
630 {
631 return _parsedClassNames.contains(className);
632 }
633
634
635
636
637
638
639
640
641
642
643 public void parse (String className, ClassNameResolver resolver)
644 throws Exception
645 {
646 if (className == null)
647 return;
648
649 if (!resolver.isExcluded(className))
650 {
651 if (!isParsed(className) || resolver.shouldOverride(className))
652 {
653 className = className.replace('.', '/')+".class";
654 URL resource = Loader.getResource(this.getClass(), className, false);
655 if (resource!= null)
656 {
657 Resource r = Resource.newResource(resource);
658 scanClass(r.getInputStream());
659 }
660 }
661 }
662 }
663
664
665
666
667
668
669
670
671
672
673
674 public void parse (Class<?> clazz, ClassNameResolver resolver, boolean visitSuperClasses)
675 throws Exception
676 {
677 Class<?> cz = clazz;
678 while (cz != null)
679 {
680 if (!resolver.isExcluded(cz.getName()))
681 {
682 if (!isParsed(cz.getName()) || resolver.shouldOverride(cz.getName()))
683 {
684 String nameAsResource = cz.getName().replace('.', '/')+".class";
685 URL resource = Loader.getResource(this.getClass(), nameAsResource, false);
686 if (resource!= null)
687 {
688 Resource r = Resource.newResource(resource);
689 scanClass(r.getInputStream());
690 }
691 }
692 }
693 if (visitSuperClasses)
694 cz = cz.getSuperclass();
695 else
696 cz = null;
697 }
698 }
699
700
701
702
703
704
705
706
707
708
709 public void parse (String[] classNames, ClassNameResolver resolver)
710 throws Exception
711 {
712 if (classNames == null)
713 return;
714
715 parse(Arrays.asList(classNames), resolver);
716 }
717
718
719
720
721
722
723
724
725
726 public void parse (List<String> classNames, ClassNameResolver resolver)
727 throws Exception
728 {
729 for (String s:classNames)
730 {
731 if ((resolver == null) || (!resolver.isExcluded(s) && (!isParsed(s) || resolver.shouldOverride(s))))
732 {
733 s = s.replace('.', '/')+".class";
734 URL resource = Loader.getResource(this.getClass(), s, false);
735 if (resource!= null)
736 {
737 Resource r = Resource.newResource(resource);
738 scanClass(r.getInputStream());
739 }
740 }
741 }
742 }
743
744
745
746
747
748
749
750
751
752 public void parse (Resource dir, ClassNameResolver resolver)
753 throws Exception
754 {
755 if (!dir.isDirectory() || !dir.exists())
756 return;
757
758
759 String[] files=dir.list();
760 for (int f=0;files!=null && f<files.length;f++)
761 {
762 try
763 {
764 Resource res = dir.addPath(files[f]);
765 if (res.isDirectory())
766 parse(res, resolver);
767 String name = res.getName();
768 if (name.endsWith(".class"))
769 {
770 if ((resolver == null)|| (!resolver.isExcluded(name) && (!isParsed(name) || resolver.shouldOverride(name))))
771 {
772 Resource r = Resource.newResource(res.getURL());
773 scanClass(r.getInputStream());
774 }
775
776 }
777 }
778 catch (Exception ex)
779 {
780 LOG.warn(Log.EXCEPTION,ex);
781 }
782 }
783 }
784
785
786
787
788
789
790
791
792
793
794
795
796 public void parse (ClassLoader loader, boolean visitParents, boolean nullInclusive, final ClassNameResolver resolver)
797 throws Exception
798 {
799 if (loader==null)
800 return;
801
802 if (!(loader instanceof URLClassLoader))
803 return;
804
805 JarScanner scanner = new JarScanner()
806 {
807 @Override
808 public void processEntry(URI jarUri, JarEntry entry)
809 {
810 try
811 {
812 String name = entry.getName();
813 if (name.toLowerCase(Locale.ENGLISH).endsWith(".class"))
814 {
815 String shortName = name.replace('/', '.').substring(0,name.length()-6);
816 if ((resolver == null)
817 ||
818 (!resolver.isExcluded(shortName) && (!isParsed(shortName) || resolver.shouldOverride(shortName))))
819 {
820
821 Resource clazz = Resource.newResource("jar:"+jarUri+"!/"+name);
822 scanClass(clazz.getInputStream());
823 }
824 }
825 }
826 catch (Exception e)
827 {
828 LOG.warn("Problem processing jar entry "+entry, e);
829 }
830 }
831
832 };
833
834 scanner.scan(null, loader, nullInclusive, visitParents);
835 }
836
837
838
839
840
841
842
843
844
845 public void parse (URI[] uris, final ClassNameResolver resolver)
846 throws Exception
847 {
848 if (uris==null)
849 return;
850
851 JarScanner scanner = new JarScanner()
852 {
853 @Override
854 public void processEntry(URI jarUri, JarEntry entry)
855 {
856 try
857 {
858 String name = entry.getName();
859 if (name.toLowerCase(Locale.ENGLISH).endsWith(".class"))
860 {
861 String shortName = name.replace('/', '.').substring(0,name.length()-6);
862
863 if ((resolver == null)
864 ||
865 (!resolver.isExcluded(shortName) && (!isParsed(shortName) || resolver.shouldOverride(shortName))))
866 {
867 Resource clazz = Resource.newResource("jar:"+jarUri+"!/"+name);
868 scanClass(clazz.getInputStream());
869
870 }
871 }
872 }
873 catch (Exception e)
874 {
875 LOG.warn("Problem processing jar entry "+entry, e);
876 }
877 }
878
879 };
880 scanner.scan(null, uris, true);
881 }
882
883
884
885
886
887
888
889 public void parse (URI uri, final ClassNameResolver resolver)
890 throws Exception
891 {
892 if (uri == null)
893 return;
894 URI[] uris = {uri};
895 parse(uris, resolver);
896 }
897
898
899
900
901
902
903
904
905
906 protected void scanClass (InputStream is)
907 throws IOException
908 {
909 ClassReader reader = new ClassReader(is);
910 reader.accept(new MyClassVisitor(), ClassReader.SKIP_CODE|ClassReader.SKIP_DEBUG|ClassReader.SKIP_FRAMES);
911 }
912 }
913