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
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
418
419
420
421 @Override
422 public void configure(WebAppContext context) throws Exception
423 {
424 context.getObjectFactory().addDecorator(new AnnotationDecorator(context));
425
426
427
428 if (!context.getMetaData().isMetaDataComplete())
429 {
430
431 if (context.getServletContext().getEffectiveMajorVersion() >= 3 || context.isConfigurationDiscovered())
432 {
433 _discoverableAnnotationHandlers.add(new WebServletAnnotationHandler(context));
434 _discoverableAnnotationHandlers.add(new WebFilterAnnotationHandler(context));
435 _discoverableAnnotationHandlers.add(new WebListenerAnnotationHandler(context));
436 }
437 }
438
439
440
441 createServletContainerInitializerAnnotationHandlers(context, getNonExcludedInitializers(context));
442
443 if (!_discoverableAnnotationHandlers.isEmpty() || _classInheritanceHandler != null || !_containerInitializerAnnotationHandlers.isEmpty())
444 scanForAnnotations(context);
445
446
447 List<ContainerInitializer> initializers =
448 (List<ContainerInitializer>)context.getAttribute(AnnotationConfiguration.CONTAINER_INITIALIZERS);
449 if (initializers != null && initializers.size()>0)
450 {
451 Map<String, Set<String>> map = ( Map<String, Set<String>>) context.getAttribute(AnnotationConfiguration.CLASS_INHERITANCE_MAP);
452 if (map == null)
453 LOG.warn ("ServletContainerInitializers: detected. Class hierarchy: empty");
454 for (ContainerInitializer i : initializers)
455 i.resolveClasses(context,map);
456 }
457 }
458
459
460
461
462
463 @Override
464 public void postConfigure(WebAppContext context) throws Exception
465 {
466 ConcurrentHashMap<String, ConcurrentHashSet<String>> classMap = (ClassInheritanceMap)context.getAttribute(CLASS_INHERITANCE_MAP);
467 List<ContainerInitializer> initializers = (List<ContainerInitializer>)context.getAttribute(CONTAINER_INITIALIZERS);
468
469 context.removeAttribute(CLASS_INHERITANCE_MAP);
470 if (classMap != null)
471 classMap.clear();
472
473 context.removeAttribute(CONTAINER_INITIALIZERS);
474 if (initializers != null)
475 initializers.clear();
476
477 if (_discoverableAnnotationHandlers != null)
478 _discoverableAnnotationHandlers.clear();
479
480 _classInheritanceHandler = null;
481 if (_containerInitializerAnnotationHandlers != null)
482 _containerInitializerAnnotationHandlers.clear();
483
484 if (_parserTasks != null)
485 {
486 _parserTasks.clear();
487 _parserTasks = null;
488 }
489
490 super.postConfigure(context);
491 }
492
493
494
495
496
497
498
499
500
501 protected void scanForAnnotations (WebAppContext context)
502 throws Exception
503 {
504 AnnotationParser parser = createAnnotationParser();
505 _parserTasks = new ArrayList<ParserTask>();
506
507 long start = 0;
508
509
510 if (LOG.isDebugEnabled())
511 LOG.debug("Annotation scanning commencing: webxml={}, metadatacomplete={}, configurationDiscovered={}, multiThreaded={}, maxScanWait={}",
512 context.getServletContext().getEffectiveMajorVersion(),
513 context.getMetaData().isMetaDataComplete(),
514 context.isConfigurationDiscovered(),
515 isUseMultiThreading(context),
516 getMaxScanWait(context));
517
518
519 parseContainerPath(context, parser);
520
521
522
523
524
525 parseWebInfClasses(context, parser);
526 parseWebInfLib (context, parser);
527
528 start = System.nanoTime();
529
530
531 final Semaphore task_limit = (isUseMultiThreading(context)? new Semaphore(Runtime.getRuntime().availableProcessors()):new Semaphore(1));
532 final CountDownLatch latch = new CountDownLatch(_parserTasks.size());
533 final MultiException me = new MultiException();
534
535 for (final ParserTask p:_parserTasks)
536 {
537 task_limit.acquire();
538 context.getServer().getThreadPool().execute(new Runnable()
539 {
540 @Override
541 public void run()
542 {
543 try
544 {
545 p.call();
546 }
547 catch (Exception e)
548 {
549 me.add(e);
550 }
551 finally
552 {
553 task_limit.release();
554 latch.countDown();
555 }
556 }
557 });
558 }
559
560 boolean timeout = !latch.await(getMaxScanWait(context), TimeUnit.SECONDS);
561
562 if (LOG.isDebugEnabled())
563 {
564 for (ParserTask p:_parserTasks)
565 LOG.debug("Scanned {} in {}ms", p.getResource(), TimeUnit.MILLISECONDS.convert(p.getStatistic().getElapsed(), TimeUnit.NANOSECONDS));
566
567 LOG.debug("Scanned {} container path jars, {} WEB-INF/lib jars, {} WEB-INF/classes dirs in {}ms for context {}",
568 _containerPathStats.getTotal(), _webInfLibStats.getTotal(), _webInfClassesStats.getTotal(),
569 (TimeUnit.MILLISECONDS.convert(System.nanoTime()-start, TimeUnit.NANOSECONDS)),
570 context);
571 }
572
573 if (timeout)
574 me.add(new Exception("Timeout scanning annotations"));
575 me.ifExceptionThrow();
576 }
577
578
579
580
581
582
583
584 protected AnnotationParser createAnnotationParser()
585 {
586 return new AnnotationParser();
587 }
588
589
590
591
592
593
594
595 protected boolean isUseMultiThreading(WebAppContext context)
596 {
597
598 Object o = context.getAttribute(MULTI_THREADED);
599 if (o instanceof Boolean)
600 {
601 return ((Boolean)o).booleanValue();
602 }
603
604 o = context.getServer().getAttribute(MULTI_THREADED);
605 if (o instanceof Boolean)
606 {
607 return ((Boolean)o).booleanValue();
608 }
609
610 return Boolean.valueOf(System.getProperty(MULTI_THREADED, Boolean.toString(DEFAULT_MULTI_THREADED)));
611 }
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 @Override
644 public void cloneConfigure(WebAppContext template, WebAppContext context) throws Exception
645 {
646 context.getObjectFactory().addDecorator(new AnnotationDecorator(context));
647 }
648
649 public void createServletContainerInitializerAnnotationHandlers (WebAppContext context, List<ServletContainerInitializer> scis)
650 throws Exception
651 {
652 if (scis == null || scis.isEmpty())
653 return;
654
655 List<ContainerInitializer> initializers = new ArrayList<ContainerInitializer>();
656 context.setAttribute(CONTAINER_INITIALIZERS, initializers);
657
658 for (ServletContainerInitializer service : scis)
659 {
660 HandlesTypes annotation = service.getClass().getAnnotation(HandlesTypes.class);
661 ContainerInitializer initializer = null;
662 if (annotation != null)
663 {
664
665 Class<?>[] classes = annotation.value();
666 if (classes != null)
667 {
668
669 if (LOG.isDebugEnabled()){LOG.debug("HandlesTypes {} on initializer {}",Arrays.asList(classes),service.getClass());}
670
671 initializer = new ContainerInitializer(service, classes);
672
673
674
675 if (context.getAttribute(CLASS_INHERITANCE_MAP) == null)
676 {
677
678 ConcurrentHashMap<String, ConcurrentHashSet<String>> map = new ClassInheritanceMap();
679 context.setAttribute(CLASS_INHERITANCE_MAP, map);
680 _classInheritanceHandler = new ClassInheritanceHandler(map);
681 }
682
683 for (Class<?> c: classes)
684 {
685
686
687 if (c.isAnnotation())
688 {
689 if (LOG.isDebugEnabled()) LOG.debug("Registering annotation handler for "+c.getName());
690 _containerInitializerAnnotationHandlers.add(new ContainerInitializerAnnotationHandler(initializer, c));
691 }
692 }
693 }
694 else
695 {
696 initializer = new ContainerInitializer(service, null);
697 if (LOG.isDebugEnabled()) LOG.debug("No classes in HandlesTypes on initializer "+service.getClass());
698 }
699 }
700 else
701 {
702 initializer = new ContainerInitializer(service, null);
703 if (LOG.isDebugEnabled()) LOG.debug("No HandlesTypes annotation on initializer "+service.getClass());
704 }
705
706 initializers.add(initializer);
707 }
708
709
710
711 ServletContainerInitializersStarter starter = (ServletContainerInitializersStarter)context.getAttribute(CONTAINER_INITIALIZER_STARTER);
712 if (starter != null)
713 throw new IllegalStateException("ServletContainerInitializersStarter already exists");
714 starter = new ServletContainerInitializersStarter(context);
715 context.setAttribute(CONTAINER_INITIALIZER_STARTER, starter);
716 context.addBean(starter, true);
717 }
718
719 public Resource getJarFor (ServletContainerInitializer service)
720 throws MalformedURLException, IOException
721 {
722
723 URL jarURL = Thread.currentThread().getContextClassLoader().getResource(service.getClass().getName().replace('.','/')+".class");
724
725
726
727 if (jarURL == null)
728 jarURL = service.getClass().getClassLoader().getResource(service.getClass().getName().replace('.','/')+".class");
729
730 String loadingJarName = jarURL.toString();
731
732 int i = loadingJarName.indexOf(".jar");
733 if (i < 0)
734 return null;
735
736 loadingJarName = loadingJarName.substring(0,i+4);
737 loadingJarName = (loadingJarName.startsWith("jar:")?loadingJarName.substring(4):loadingJarName);
738 return Resource.newResource(loadingJarName);
739 }
740
741
742
743
744
745
746
747
748
749
750
751 public boolean isFromExcludedJar (WebAppContext context, ServletContainerInitializer sci, Resource sciResource)
752 throws Exception
753 {
754 if (sci == null)
755 throw new IllegalArgumentException("ServletContainerInitializer null");
756 if (context == null)
757 throw new IllegalArgumentException("WebAppContext null");
758
759 if (LOG.isDebugEnabled()) LOG.debug("Checking {} for jar exclusion", sci);
760
761
762
763 if (isFromContainerClassPath(context, sci))
764 return false;
765
766
767 if (context.getMetaData().getOrdering() == null)
768 return false;
769
770
771 List<Resource> orderedJars = context.getMetaData().getOrderedWebInfJars();
772
773
774 if (orderedJars.isEmpty())
775 return true;
776
777 if (sciResource == null)
778 return false;
779
780 URI loadingJarURI = sciResource.getURI();
781 boolean found = false;
782 Iterator<Resource> itor = orderedJars.iterator();
783 while (!found && itor.hasNext())
784 {
785 Resource r = itor.next();
786 found = r.getURI().equals(loadingJarURI);
787 }
788
789 return !found;
790 }
791
792
793
794
795
796
797
798
799
800 public boolean matchesExclusionPattern(ServletContainerInitializer sci)
801 {
802
803 if (_sciExcludePattern == null)
804 return false;
805
806
807 if (LOG.isDebugEnabled()) LOG.debug("Checking {} against containerInitializerExclusionPattern",sci.getClass().getName());
808 return _sciExcludePattern.matcher(sci.getClass().getName()).matches();
809 }
810
811
812
813
814
815
816
817
818
819 public boolean isFromContainerClassPath (WebAppContext context, ServletContainerInitializer sci)
820 {
821 if (sci == null)
822 return false;
823 return sci.getClass().getClassLoader()==context.getClassLoader().getParent();
824 }
825
826 public List<ServletContainerInitializer> getNonExcludedInitializers (WebAppContext context)
827 throws Exception
828 {
829 ArrayList<ServletContainerInitializer> nonExcludedInitializers = new ArrayList<ServletContainerInitializer>();
830
831
832 long start = 0;
833
834 ClassLoader old = Thread.currentThread().getContextClassLoader();
835 ServiceLoader<ServletContainerInitializer> loadedInitializers = null;
836 try
837 {
838 if (LOG.isDebugEnabled())
839 start = System.nanoTime();
840 Thread.currentThread().setContextClassLoader(context.getClassLoader());
841 loadedInitializers = ServiceLoader.load(ServletContainerInitializer.class);
842 }
843 finally
844 {
845 Thread.currentThread().setContextClassLoader(old);
846 }
847
848 if (LOG.isDebugEnabled())
849 LOG.debug("Service loaders found in {}ms", (TimeUnit.MILLISECONDS.convert((System.nanoTime()-start), TimeUnit.NANOSECONDS)));
850
851
852 Map<ServletContainerInitializer,Resource> sciResourceMap = new HashMap<ServletContainerInitializer,Resource>();
853 ServletContainerInitializerOrdering initializerOrdering = getInitializerOrdering(context);
854
855
856
857 for (ServletContainerInitializer sci:loadedInitializers)
858 {
859 if (matchesExclusionPattern(sci))
860 {
861 if (LOG.isDebugEnabled()) LOG.debug("{} excluded by pattern", sci);
862 continue;
863 }
864
865 Resource sciResource = getJarFor(sci);
866 if (isFromExcludedJar(context, sci, sciResource))
867 {
868 if (LOG.isDebugEnabled()) LOG.debug("{} is from excluded jar", sci);
869 continue;
870 }
871
872
873 String name = sci.getClass().getName();
874 if (initializerOrdering != null
875 && (!initializerOrdering.hasWildcard() && initializerOrdering.getIndexOf(name) < 0))
876 {
877 if (LOG.isDebugEnabled()) LOG.debug("{} is excluded by ordering", sci);
878 continue;
879 }
880
881 sciResourceMap.put(sci, sciResource);
882 }
883
884
885 if (initializerOrdering != null && !initializerOrdering.isDefaultOrder())
886 {
887 if (LOG.isDebugEnabled())
888 LOG.debug("Ordering ServletContainerInitializers with "+initializerOrdering);
889
890
891
892 nonExcludedInitializers.addAll(sciResourceMap.keySet());
893 Collections.sort(nonExcludedInitializers, new ServletContainerInitializerComparator(initializerOrdering));
894 }
895 else
896 {
897
898
899
900
901
902 if (context.getMetaData().getOrdering() == null)
903 {
904 if (LOG.isDebugEnabled()) LOG.debug("No web.xml ordering, ServletContainerInitializers in random order");
905 nonExcludedInitializers.addAll(sciResourceMap.keySet());
906 }
907 else
908 {
909 if (LOG.isDebugEnabled()) LOG.debug("Ordering ServletContainerInitializers with ordering {}",context.getMetaData().getOrdering());
910 for (Map.Entry<ServletContainerInitializer, Resource> entry:sciResourceMap.entrySet())
911 {
912
913 if (entry.getKey().getClass().getClassLoader()==context.getClassLoader().getParent())
914 nonExcludedInitializers.add(entry.getKey());
915 else if (entry.getValue() == null)
916 nonExcludedInitializers.add(entry.getKey());
917 }
918
919
920 for (Resource webInfJar:context.getMetaData().getOrderedWebInfJars())
921 {
922 for (Map.Entry<ServletContainerInitializer, Resource> entry:sciResourceMap.entrySet())
923 {
924 if (webInfJar.equals(entry.getValue()))
925 nonExcludedInitializers.add(entry.getKey());
926 }
927 }
928 }
929 }
930
931 if (LOG.isDebugEnabled())
932 {
933 int i=0;
934 for (ServletContainerInitializer sci:nonExcludedInitializers)
935 LOG.debug("ServletContainerInitializer: {} {} from {}",(++i), sci.getClass().getName(), sciResourceMap.get(sci));
936 }
937 return nonExcludedInitializers;
938 }
939
940
941
942
943
944
945
946
947 public ServletContainerInitializerOrdering getInitializerOrdering (WebAppContext context)
948 {
949 if (context == null)
950 return null;
951
952 String tmp = (String)context.getAttribute(SERVLET_CONTAINER_INITIALIZER_ORDER);
953 if (tmp == null || "".equals(tmp.trim()))
954 return null;
955
956 return new ServletContainerInitializerOrdering(tmp);
957 }
958
959
960
961
962
963
964
965
966
967 public void parseContainerPath (final WebAppContext context, final AnnotationParser parser) throws Exception
968 {
969
970 final Set<Handler> handlers = new HashSet<Handler>();
971 handlers.addAll(_discoverableAnnotationHandlers);
972 handlers.addAll(_containerInitializerAnnotationHandlers);
973 if (_classInheritanceHandler != null)
974 handlers.add(_classInheritanceHandler);
975
976 _containerPathStats = new CounterStatistic();
977
978 for (Resource r : context.getMetaData().getContainerResources())
979 {
980
981 if (_parserTasks != null)
982 {
983 ParserTask task = new ParserTask(parser, handlers, r, _containerClassNameResolver);
984 _parserTasks.add(task);
985 _containerPathStats.increment();
986 if (LOG.isDebugEnabled())
987 task.setStatistic(new TimeStatistic());
988 }
989 }
990 }
991
992
993
994
995
996
997
998
999
1000 public void parseWebInfLib (final WebAppContext context, final AnnotationParser parser) throws Exception
1001 {
1002 List<FragmentDescriptor> frags = context.getMetaData().getFragments();
1003
1004
1005
1006
1007 ArrayList<URI> webInfUris = new ArrayList<URI>();
1008
1009 List<Resource> jars = null;
1010
1011 if (context.getMetaData().getOrdering() != null)
1012 jars = context.getMetaData().getOrderedWebInfJars();
1013 else
1014
1015 jars = context.getMetaData().getWebInfJars();
1016
1017 _webInfLibStats = new CounterStatistic();
1018
1019 for (Resource r : jars)
1020 {
1021
1022 final Set<Handler> handlers = new HashSet<Handler>();
1023
1024 FragmentDescriptor f = getFragmentFromJar(r, frags);
1025
1026
1027
1028
1029
1030 if (f == null || !isMetaDataComplete(f) || _classInheritanceHandler != null || !_containerInitializerAnnotationHandlers.isEmpty())
1031 {
1032
1033 if (_classInheritanceHandler != null)
1034 handlers.add(_classInheritanceHandler);
1035
1036
1037 handlers.addAll(_containerInitializerAnnotationHandlers);
1038
1039
1040 if (f == null || !isMetaDataComplete(f))
1041 handlers.addAll(_discoverableAnnotationHandlers);
1042
1043 if (_parserTasks != null)
1044 {
1045 ParserTask task = new ParserTask(parser, handlers,r, _webAppClassNameResolver);
1046 _parserTasks.add (task);
1047 _webInfLibStats.increment();
1048 if (LOG.isDebugEnabled())
1049 task.setStatistic(new TimeStatistic());
1050 }
1051 }
1052 }
1053 }
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063 public void parseWebInfClasses (final WebAppContext context, final AnnotationParser parser)
1064 throws Exception
1065 {
1066 Set<Handler> handlers = new HashSet<Handler>();
1067 handlers.addAll(_discoverableAnnotationHandlers);
1068 if (_classInheritanceHandler != null)
1069 handlers.add(_classInheritanceHandler);
1070 handlers.addAll(_containerInitializerAnnotationHandlers);
1071
1072 _webInfClassesStats = new CounterStatistic();
1073
1074 for (Resource dir : context.getMetaData().getWebInfClassesDirs())
1075 {
1076 if (_parserTasks != null)
1077 {
1078 ParserTask task = new ParserTask(parser, handlers, dir, _webAppClassNameResolver);
1079 _parserTasks.add(task);
1080 _webInfClassesStats.increment();
1081 if (LOG.isDebugEnabled())
1082 task.setStatistic(new TimeStatistic());
1083 }
1084 }
1085 }
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097 public FragmentDescriptor getFragmentFromJar (Resource jar, List<FragmentDescriptor> frags)
1098 throws Exception
1099 {
1100
1101 FragmentDescriptor d = null;
1102 for (FragmentDescriptor frag: frags)
1103 {
1104 Resource fragResource = frag.getResource();
1105 if (Resource.isContainedIn(fragResource,jar))
1106 {
1107 d = frag;
1108 break;
1109 }
1110 }
1111 return d;
1112 }
1113
1114 public boolean isMetaDataComplete (WebDescriptor d)
1115 {
1116 return (d!=null && d.getMetaDataComplete() == MetaDataComplete.True);
1117 }
1118
1119 public static class ClassInheritanceMap extends ConcurrentHashMap<String, ConcurrentHashSet<String>>
1120 {
1121
1122 @Override
1123 public String toString()
1124 {
1125 return String.format("ClassInheritanceMap@%x{size=%d}",hashCode(),size());
1126 }
1127 }
1128 }
1129
1130