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