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