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.net.MalformedURLException;
23 import java.net.URI;
24 import java.util.ArrayList;
25 import java.util.Collections;
26 import java.util.Comparator;
27 import java.util.HashMap;
28 import java.util.HashSet;
29 import java.util.Iterator;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.ServiceLoader;
33 import java.util.Set;
34 import java.util.concurrent.Callable;
35 import java.util.concurrent.ConcurrentHashMap;
36 import java.util.concurrent.CountDownLatch;
37 import java.util.concurrent.Semaphore;
38 import java.util.concurrent.TimeUnit;
39
40 import javax.servlet.ServletContainerInitializer;
41 import javax.servlet.annotation.HandlesTypes;
42
43 import org.eclipse.jetty.annotations.AnnotationParser.Handler;
44 import org.eclipse.jetty.plus.annotation.ContainerInitializer;
45 import org.eclipse.jetty.util.ConcurrentHashSet;
46 import org.eclipse.jetty.util.MultiException;
47 import org.eclipse.jetty.util.log.Log;
48 import org.eclipse.jetty.util.log.Logger;
49 import org.eclipse.jetty.util.resource.Resource;
50 import org.eclipse.jetty.webapp.AbstractConfiguration;
51 import org.eclipse.jetty.webapp.FragmentDescriptor;
52 import org.eclipse.jetty.webapp.MetaDataComplete;
53 import org.eclipse.jetty.webapp.WebAppContext;
54 import org.eclipse.jetty.webapp.WebDescriptor;
55
56
57
58
59
60
61 public class AnnotationConfiguration extends AbstractConfiguration
62 {
63 private static final Logger LOG = Log.getLogger(AnnotationConfiguration.class);
64
65 public static final String SERVLET_CONTAINER_INITIALIZER_ORDER = "org.eclipse.jetty.containerInitializerOrder";
66 public static final String CLASS_INHERITANCE_MAP = "org.eclipse.jetty.classInheritanceMap";
67 public static final String CONTAINER_INITIALIZERS = "org.eclipse.jetty.containerInitializers";
68 public static final String CONTAINER_INITIALIZER_STARTER = "org.eclipse.jetty.containerInitializerStarter";
69 public static final String MULTI_THREADED = "org.eclipse.jetty.annotations.multiThreaded";
70 public static final String MAX_SCAN_WAIT = "org.eclipse.jetty.annotations.maxWait";
71
72 public static final int DEFAULT_MAX_SCAN_WAIT = 60;
73 public static final boolean DEFAULT_MULTI_THREADED = true;
74
75 protected List<AbstractDiscoverableAnnotationHandler> _discoverableAnnotationHandlers = new ArrayList<AbstractDiscoverableAnnotationHandler>();
76 protected ClassInheritanceHandler _classInheritanceHandler;
77 protected List<ContainerInitializerAnnotationHandler> _containerInitializerAnnotationHandlers = new ArrayList<ContainerInitializerAnnotationHandler>();
78
79 protected List<ParserTask> _parserTasks;
80 protected WebAppClassNameResolver _webAppClassNameResolver;
81 protected ContainerClassNameResolver _containerClassNameResolver;
82
83
84
85
86
87
88
89
90
91 public class ParserTask implements Callable<Void>
92 {
93 protected Exception _exception;
94 protected final AnnotationParser _parser;
95 protected final Set<? extends Handler> _handlers;
96 protected final ClassNameResolver _resolver;
97 protected final Resource _resource;
98
99
100 public ParserTask (AnnotationParser parser, Set<? extends Handler>handlers, Resource resource, ClassNameResolver resolver)
101 {
102 _parser = parser;
103 _handlers = handlers;
104 _resolver = resolver;
105 _resource = resource;
106 }
107
108 public Void call() throws Exception
109 {
110 if (_parser != null)
111 _parser.parse(_handlers, _resource, _resolver);
112 return null;
113 }
114 }
115
116
117
118
119
120
121
122
123
124
125
126
127
128 public class WebAppClassNameResolver implements ClassNameResolver
129 {
130 private WebAppContext _context;
131
132 public WebAppClassNameResolver (WebAppContext context)
133 {
134 _context = context;
135 }
136
137 public boolean isExcluded (String name)
138 {
139 if (_context.isSystemClass(name)) return true;
140 if (_context.isServerClass(name)) return false;
141 return false;
142 }
143
144 public boolean shouldOverride (String name)
145 {
146
147
148 if (_context.isParentLoaderPriority())
149 return false;
150 return true;
151 }
152 }
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167 public class ContainerClassNameResolver implements ClassNameResolver
168 {
169 private WebAppContext _context;
170
171 public ContainerClassNameResolver (WebAppContext context)
172 {
173 _context = context;
174 }
175 public boolean isExcluded (String name)
176 {
177 if (_context.isSystemClass(name)) return false;
178 if (_context.isServerClass(name)) return true;
179 return false;
180 }
181
182 public boolean shouldOverride (String name)
183 {
184
185 if (_context.isParentLoaderPriority())
186 return true;
187 return false;
188 }
189 }
190
191
192
193
194
195
196
197
198
199
200 public class ServletContainerInitializerOrdering
201 {
202 private Map<String, Integer> _indexMap = new HashMap<String, Integer>();
203 private Integer _star = null;
204 private String _ordering = null;
205
206 public ServletContainerInitializerOrdering (String ordering)
207 {
208 if (ordering != null)
209 {
210 _ordering = ordering;
211
212 String[] tmp = ordering.split(",");
213
214 for (int i=0; i<tmp.length; i++)
215 {
216 String s = tmp[i].trim();
217 _indexMap.put(s, Integer.valueOf(i));
218 if ("*".equals(s))
219 {
220 if (_star != null)
221 throw new IllegalArgumentException("Duplicate wildcards in ServletContainerInitializer ordering "+ordering);
222 _star = Integer.valueOf(i);
223 }
224
225 }
226 }
227 }
228
229
230
231
232
233 public boolean hasWildcard()
234 {
235 return _star != null;
236 }
237
238
239
240
241
242 public int getWildcardIndex()
243 {
244 if (!hasWildcard())
245 return -1;
246 return _star.intValue();
247 }
248
249
250
251
252
253 public boolean isDefaultOrder ()
254 {
255 return (getSize() == 1 && hasWildcard());
256 }
257
258
259
260
261
262
263 public int getIndexOf (String name)
264 {
265 Integer i = _indexMap.get(name);
266 if (i == null)
267 return -1;
268 return i.intValue();
269 }
270
271
272
273
274
275 public int getSize()
276 {
277 return _indexMap.size();
278 }
279
280 public String toString()
281 {
282 if (_ordering == null)
283 return "";
284 return _ordering;
285 }
286 }
287
288
289
290
291
292
293
294
295
296
297
298 public class ServletContainerInitializerComparator implements Comparator<ServletContainerInitializer>
299 {
300 private ServletContainerInitializerOrdering _ordering;
301
302
303 public ServletContainerInitializerComparator (ServletContainerInitializerOrdering ordering)
304 {
305 _ordering = ordering;
306 }
307
308 @Override
309 public int compare(ServletContainerInitializer sci1, ServletContainerInitializer sci2)
310 {
311 String c1 = (sci1 != null? sci1.getClass().getName() : null);
312 String c2 = (sci2 != null? sci2.getClass().getName() : null);
313
314 if (c1 == null && c2 == null)
315 return 0;
316
317 int i1 = _ordering.getIndexOf(c1);
318 if (i1 < 0 && _ordering.hasWildcard())
319 i1 = _ordering.getWildcardIndex();
320 int i2 = _ordering.getIndexOf(c2);
321 if (i2 < 0 && _ordering.hasWildcard())
322 i2 = _ordering.getWildcardIndex();
323
324 return Integer.compare(i1, i2);
325 }
326 }
327
328 @Override
329 public void preConfigure(final WebAppContext context) throws Exception
330 {
331 _webAppClassNameResolver = new WebAppClassNameResolver(context);
332 _containerClassNameResolver = new ContainerClassNameResolver(context);
333 }
334
335
336 public void addDiscoverableAnnotationHandler(AbstractDiscoverableAnnotationHandler handler)
337 {
338 _discoverableAnnotationHandlers.add(handler);
339 }
340
341 @Override
342 public void deconfigure(WebAppContext context) throws Exception
343 {
344 context.removeAttribute(CLASS_INHERITANCE_MAP);
345 context.removeAttribute(CONTAINER_INITIALIZERS);
346 ServletContainerInitializersStarter starter = (ServletContainerInitializersStarter)context.getAttribute(CONTAINER_INITIALIZER_STARTER);
347 if (starter != null)
348 {
349 context.removeBean(starter);
350 context.removeAttribute(CONTAINER_INITIALIZER_STARTER);
351 }
352 }
353
354
355
356
357 @Override
358 public void configure(WebAppContext context) throws Exception
359 {
360 context.addDecorator(new AnnotationDecorator(context));
361
362
363
364 if (!context.getMetaData().isMetaDataComplete())
365 {
366
367 if (context.getServletContext().getEffectiveMajorVersion() >= 3 || context.isConfigurationDiscovered())
368 {
369 _discoverableAnnotationHandlers.add(new WebServletAnnotationHandler(context));
370 _discoverableAnnotationHandlers.add(new WebFilterAnnotationHandler(context));
371 _discoverableAnnotationHandlers.add(new WebListenerAnnotationHandler(context));
372 }
373 }
374
375
376
377 createServletContainerInitializerAnnotationHandlers(context, getNonExcludedInitializers(context));
378
379 if (!_discoverableAnnotationHandlers.isEmpty() || _classInheritanceHandler != null || !_containerInitializerAnnotationHandlers.isEmpty())
380 scanForAnnotations(context);
381 }
382
383
384
385
386
387
388 @Override
389 public void postConfigure(WebAppContext context) throws Exception
390 {
391 ConcurrentHashMap<String, ConcurrentHashSet<String>> classMap = (ConcurrentHashMap<String, ConcurrentHashSet<String>>)context.getAttribute(CLASS_INHERITANCE_MAP);
392 List<ContainerInitializer> initializers = (List<ContainerInitializer>)context.getAttribute(CONTAINER_INITIALIZERS);
393
394 context.removeAttribute(CLASS_INHERITANCE_MAP);
395 if (classMap != null)
396 classMap.clear();
397
398 context.removeAttribute(CONTAINER_INITIALIZERS);
399 if (initializers != null)
400 initializers.clear();
401
402 if (_discoverableAnnotationHandlers != null)
403 _discoverableAnnotationHandlers.clear();
404
405 _classInheritanceHandler = null;
406 if (_containerInitializerAnnotationHandlers != null)
407 _containerInitializerAnnotationHandlers.clear();
408
409 if (_parserTasks != null)
410 {
411 _parserTasks.clear();
412 _parserTasks = null;
413 }
414
415 super.postConfigure(context);
416 }
417
418
419
420
421
422
423
424
425
426 protected void scanForAnnotations (WebAppContext context)
427 throws Exception
428 {
429 AnnotationParser parser = createAnnotationParser();
430 _parserTasks = new ArrayList<ParserTask>();
431
432 long start = 0;
433
434 if (LOG.isDebugEnabled())
435 {
436 LOG.debug("Scanning for annotations: webxml={}, metadatacomplete={}, configurationDiscovered={}, multiThreaded={}, maxScanWait={}",
437 context.getServletContext().getEffectiveMajorVersion(),
438 context.getMetaData().isMetaDataComplete(),
439 context.isConfigurationDiscovered(),
440 isUseMultiThreading(context),
441 getMaxScanWait(context));
442 }
443
444 parseContainerPath(context, parser);
445
446
447
448
449
450 parseWebInfClasses(context, parser);
451 parseWebInfLib (context, parser);
452
453
454 if (LOG.isDebugEnabled())
455 start = System.nanoTime();
456
457
458 final Semaphore task_limit = (isUseMultiThreading(context)? new Semaphore(Runtime.getRuntime().availableProcessors()):new Semaphore(1));
459 final CountDownLatch latch = new CountDownLatch(_parserTasks.size());
460 final MultiException me = new MultiException();
461
462 for (final ParserTask p:_parserTasks)
463 {
464 task_limit.acquire();
465 context.getServer().getThreadPool().execute(new Runnable()
466 {
467 @Override
468 public void run()
469 {
470 try
471 {
472 p.call();
473 }
474 catch (Exception e)
475 {
476 me.add(e);
477 }
478 finally
479 {
480 task_limit.release();
481 latch.countDown();
482 }
483 }
484 });
485 }
486
487 boolean timeout = !latch.await(getMaxScanWait(context), TimeUnit.SECONDS);
488
489 if (LOG.isDebugEnabled())
490 LOG.debug("Annotation parsing millisec={}",(TimeUnit.MILLISECONDS.convert(System.nanoTime()-start, TimeUnit.NANOSECONDS)));
491
492 if (timeout)
493 me.add(new Exception("Timeout scanning annotations"));
494 me.ifExceptionThrow();
495 }
496
497
498
499
500
501
502
503 protected AnnotationParser createAnnotationParser()
504 {
505 return new AnnotationParser();
506 }
507
508
509
510
511
512
513 protected boolean isUseMultiThreading(WebAppContext context)
514 {
515
516 Object o = context.getAttribute(MULTI_THREADED);
517 if (o instanceof Boolean)
518 {
519 return ((Boolean)o).booleanValue();
520 }
521
522 o = context.getServer().getAttribute(MULTI_THREADED);
523 if (o instanceof Boolean)
524 {
525 return ((Boolean)o).booleanValue();
526 }
527
528 return Boolean.valueOf(System.getProperty(MULTI_THREADED, Boolean.toString(DEFAULT_MULTI_THREADED)));
529 }
530
531
532
533
534
535
536
537
538
539 protected int getMaxScanWait (WebAppContext context)
540 {
541
542 Object o = context.getAttribute(MAX_SCAN_WAIT);
543 if (o != null && o instanceof Number)
544 {
545 return ((Number)o).intValue();
546 }
547
548 o = context.getServer().getAttribute(MAX_SCAN_WAIT);
549 if (o != null && o instanceof Number)
550 {
551 return ((Number)o).intValue();
552 }
553
554 return Integer.getInteger(MAX_SCAN_WAIT, DEFAULT_MAX_SCAN_WAIT).intValue();
555 }
556
557
558
559
560
561
562 @Override
563 public void cloneConfigure(WebAppContext template, WebAppContext context) throws Exception
564 {
565 context.addDecorator(new AnnotationDecorator(context));
566 }
567
568
569
570
571
572
573
574
575 public void createServletContainerInitializerAnnotationHandlers (WebAppContext context, List<ServletContainerInitializer> scis)
576 throws Exception
577 {
578 if (scis == null || scis.isEmpty())
579 return;
580
581 List<ContainerInitializer> initializers = new ArrayList<ContainerInitializer>();
582 context.setAttribute(CONTAINER_INITIALIZERS, initializers);
583
584 for (ServletContainerInitializer service : scis)
585 {
586 HandlesTypes annotation = service.getClass().getAnnotation(HandlesTypes.class);
587 ContainerInitializer initializer = null;
588 if (annotation != null)
589 {
590
591 Class[] classes = annotation.value();
592 if (classes != null)
593 {
594 initializer = new ContainerInitializer(service, classes);
595
596
597
598 if (context.getAttribute(CLASS_INHERITANCE_MAP) == null)
599 {
600
601 ConcurrentHashMap<String, ConcurrentHashSet<String>> map = new ConcurrentHashMap<String, ConcurrentHashSet<String>>();
602 context.setAttribute(CLASS_INHERITANCE_MAP, map);
603 _classInheritanceHandler = new ClassInheritanceHandler(map);
604 }
605
606 for (Class c: classes)
607 {
608
609
610 if (c.isAnnotation())
611 {
612 if (LOG.isDebugEnabled()) LOG.debug("Registering annotation handler for "+c.getName());
613 _containerInitializerAnnotationHandlers.add(new ContainerInitializerAnnotationHandler(initializer, c));
614 }
615 }
616 }
617 else
618 {
619 initializer = new ContainerInitializer(service, null);
620 if (LOG.isDebugEnabled()) LOG.debug("No classes in HandlesTypes on initializer "+service.getClass());
621 }
622 }
623 else
624 {
625 initializer = new ContainerInitializer(service, null);
626 if (LOG.isDebugEnabled()) LOG.debug("No annotation on initializer "+service.getClass());
627 }
628
629 initializers.add(initializer);
630 }
631
632
633
634 ServletContainerInitializersStarter starter = (ServletContainerInitializersStarter)context.getAttribute(CONTAINER_INITIALIZER_STARTER);
635 if (starter != null)
636 throw new IllegalStateException("ServletContainerInitializersStarter already exists");
637 starter = new ServletContainerInitializersStarter(context);
638 context.setAttribute(CONTAINER_INITIALIZER_STARTER, starter);
639 context.addBean(starter, true);
640 }
641
642
643 public Resource getJarFor (ServletContainerInitializer service)
644 throws MalformedURLException, IOException
645 {
646 String loadingJarName = Thread.currentThread().getContextClassLoader().getResource(service.getClass().getName().replace('.','/')+".class").toString();
647
648 int i = loadingJarName.indexOf(".jar");
649 if (i < 0)
650 return null;
651
652 loadingJarName = loadingJarName.substring(0,i+4);
653 loadingJarName = (loadingJarName.startsWith("jar:")?loadingJarName.substring(4):loadingJarName);
654 return Resource.newResource(loadingJarName);
655 }
656
657
658
659
660
661
662
663
664
665 public boolean isFromExcludedJar (WebAppContext context, ServletContainerInitializer sci, Resource sciResource)
666 throws Exception
667 {
668 if (sci == null)
669 throw new IllegalArgumentException("ServletContainerInitializer null");
670 if (context == null)
671 throw new IllegalArgumentException("WebAppContext null");
672
673
674
675 if (sci.getClass().getClassLoader()==context.getClassLoader().getParent())
676 return false;
677
678 List<Resource> orderedJars = context.getMetaData().getOrderedWebInfJars();
679
680
681 if (context.getMetaData().getOrdering() == null)
682 return false;
683
684
685 if (orderedJars.isEmpty())
686 return true;
687
688 if (sciResource == null)
689 return false;
690
691 URI loadingJarURI = sciResource.getURI();
692 boolean found = false;
693 Iterator<Resource> itor = orderedJars.iterator();
694 while (!found && itor.hasNext())
695 {
696 Resource r = itor.next();
697 found = r.getURI().equals(loadingJarURI);
698 }
699
700 return !found;
701 }
702
703
704
705
706
707
708
709
710 public List<ServletContainerInitializer> getNonExcludedInitializers (WebAppContext context)
711 throws Exception
712 {
713 ArrayList<ServletContainerInitializer> nonExcludedInitializers = new ArrayList<ServletContainerInitializer>();
714
715
716
717 long start = 0;
718 if (LOG.isDebugEnabled())
719 start = System.nanoTime();
720 ServiceLoader<ServletContainerInitializer> loadedInitializers = ServiceLoader.load(ServletContainerInitializer.class, context.getClassLoader());
721 if (LOG.isDebugEnabled())
722 LOG.debug("Service loaders found in {}ms", (TimeUnit.MILLISECONDS.convert((System.nanoTime()-start), TimeUnit.NANOSECONDS)));
723
724
725 if (loadedInitializers == null)
726 return Collections.emptyList();
727
728 ServletContainerInitializerOrdering initializerOrdering = getInitializerOrdering(context);
729
730 if (initializerOrdering != null && !initializerOrdering.isDefaultOrder())
731 {
732 if (LOG.isDebugEnabled())
733 LOG.debug("Ordering ServletContainerInitializers with "+initializerOrdering);
734
735
736
737 for (ServletContainerInitializer sci:loadedInitializers)
738 {
739 Resource sciResource = getJarFor(sci);
740 if (!isFromExcludedJar(context, sci, sciResource))
741 {
742 String name = sci.getClass().getName();
743 if (initializerOrdering.getIndexOf(name) >= 0 || initializerOrdering.hasWildcard())
744 nonExcludedInitializers.add(sci);
745 }
746 }
747
748
749 Collections.sort(nonExcludedInitializers, new ServletContainerInitializerComparator(initializerOrdering));
750 }
751 else
752 {
753
754
755
756 if (LOG.isDebugEnabled())
757 LOG.debug("Ordering ServletContainerInitializers as container path, webapp path");
758
759 Map<ServletContainerInitializer,Resource> webappPathInitializerResourceMap = new HashMap<ServletContainerInitializer,Resource>();
760 for (ServletContainerInitializer sci : loadedInitializers)
761 {
762
763 if (sci.getClass().getClassLoader() == context.getClassLoader().getParent())
764 {
765 nonExcludedInitializers.add(sci);
766 }
767 else
768 {
769
770 Resource sciResource = getJarFor(sci);
771 if (!isFromExcludedJar(context, sci, sciResource))
772 {
773 webappPathInitializerResourceMap.put(sci, sciResource);
774 }
775 }
776 }
777
778
779 if (context.getMetaData().getOrdering() == null)
780 nonExcludedInitializers.addAll(webappPathInitializerResourceMap.keySet());
781 else
782 {
783
784 for (Map.Entry<ServletContainerInitializer, Resource> entry:webappPathInitializerResourceMap.entrySet())
785 {
786 if (entry.getValue() == null)
787 nonExcludedInitializers.add(entry.getKey());
788 }
789
790
791 for (Resource webInfJar:context.getMetaData().getOrderedWebInfJars())
792 {
793 for (Map.Entry<ServletContainerInitializer, Resource> entry:webappPathInitializerResourceMap.entrySet())
794 {
795 if (webInfJar.equals(entry.getValue()))
796 nonExcludedInitializers.add(entry.getKey());
797 }
798 }
799 }
800 }
801
802 return nonExcludedInitializers;
803 }
804
805
806
807
808
809
810
811 public ServletContainerInitializerOrdering getInitializerOrdering (WebAppContext context)
812 {
813 if (context == null)
814 return null;
815
816 String tmp = (String)context.getAttribute(SERVLET_CONTAINER_INITIALIZER_ORDER);
817 if (tmp == null || "".equals(tmp.trim()))
818 return null;
819
820 return new ServletContainerInitializerOrdering(tmp);
821 }
822
823
824
825
826
827
828
829
830
831 public void parseContainerPath (final WebAppContext context, final AnnotationParser parser) throws Exception
832 {
833
834 LOG.debug("Scanning container jars");
835
836
837 final Set<Handler> handlers = new HashSet<Handler>();
838 handlers.addAll(_discoverableAnnotationHandlers);
839 handlers.addAll(_containerInitializerAnnotationHandlers);
840 if (_classInheritanceHandler != null)
841 handlers.add(_classInheritanceHandler);
842
843 for (Resource r : context.getMetaData().getContainerResources())
844 {
845
846 if (_parserTasks != null)
847 _parserTasks.add(new ParserTask(parser, handlers, r, _containerClassNameResolver));
848 }
849 }
850
851
852
853
854
855
856
857
858
859 public void parseWebInfLib (final WebAppContext context, final AnnotationParser parser) throws Exception
860 {
861 LOG.debug("Scanning WEB-INF/lib jars");
862
863 List<FragmentDescriptor> frags = context.getMetaData().getFragments();
864
865
866
867
868 ArrayList<URI> webInfUris = new ArrayList<URI>();
869
870 List<Resource> jars = context.getMetaData().getOrderedWebInfJars();
871
872
873 if (jars == null || jars.isEmpty())
874 jars = context.getMetaData().getWebInfJars();
875
876 for (Resource r : jars)
877 {
878
879 final Set<Handler> handlers = new HashSet<Handler>();
880
881 FragmentDescriptor f = getFragmentFromJar(r, frags);
882
883
884
885
886
887 if (f == null || !isMetaDataComplete(f) || _classInheritanceHandler != null || !_containerInitializerAnnotationHandlers.isEmpty())
888 {
889
890 if (_classInheritanceHandler != null)
891 handlers.add(_classInheritanceHandler);
892
893
894 handlers.addAll(_containerInitializerAnnotationHandlers);
895
896
897 if (f == null || !isMetaDataComplete(f))
898 handlers.addAll(_discoverableAnnotationHandlers);
899
900 if (_parserTasks != null)
901 _parserTasks.add (new ParserTask(parser, handlers,r, _webAppClassNameResolver));
902 }
903 }
904
905 }
906
907
908
909
910
911
912
913
914
915 public void parseWebInfClasses (final WebAppContext context, final AnnotationParser parser)
916 throws Exception
917 {
918 LOG.debug("Scanning WEB-INF/classes");
919
920 Set<Handler> handlers = new HashSet<Handler>();
921 handlers.addAll(_discoverableAnnotationHandlers);
922 if (_classInheritanceHandler != null)
923 handlers.add(_classInheritanceHandler);
924 handlers.addAll(_containerInitializerAnnotationHandlers);
925
926 for (Resource dir : context.getMetaData().getWebInfClassesDirs())
927 {
928 if (_parserTasks != null)
929 _parserTasks.add(new ParserTask(parser, handlers, dir, _webAppClassNameResolver));
930 }
931 }
932
933
934
935
936
937
938
939
940
941
942
943 public FragmentDescriptor getFragmentFromJar (Resource jar, List<FragmentDescriptor> frags)
944 throws Exception
945 {
946
947 FragmentDescriptor d = null;
948 for (FragmentDescriptor frag: frags)
949 {
950 Resource fragResource = frag.getResource();
951 if (Resource.isContainedIn(fragResource,jar))
952 {
953 d = frag;
954 break;
955 }
956 }
957 return d;
958 }
959
960 public boolean isMetaDataComplete (WebDescriptor d)
961 {
962 return (d!=null && d.getMetaDataComplete() == MetaDataComplete.True);
963 }
964 }