1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.webapp;
20
21 import java.lang.annotation.Annotation;
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.Map;
27
28 import javax.servlet.ServletContext;
29
30 import org.eclipse.jetty.util.log.Log;
31 import org.eclipse.jetty.util.log.Logger;
32 import org.eclipse.jetty.util.resource.EmptyResource;
33 import org.eclipse.jetty.util.resource.Resource;
34
35
36
37
38
39
40 public class MetaData
41 {
42 private static final Logger LOG = Log.getLogger(MetaData.class);
43
44 public static final String ORDERED_LIBS = "javax.servlet.context.orderedLibs";
45 public static final Resource NON_FRAG_RESOURCE = EmptyResource.INSTANCE;
46
47 protected Map<String, OriginInfo> _origins =new HashMap<String,OriginInfo>();
48 protected WebDescriptor _webDefaultsRoot;
49 protected WebDescriptor _webXmlRoot;
50 protected final List<WebDescriptor> _webOverrideRoots=new ArrayList<WebDescriptor>();
51 protected boolean _metaDataComplete;
52 protected final List<DescriptorProcessor> _descriptorProcessors = new ArrayList<DescriptorProcessor>();
53 protected final List<FragmentDescriptor> _webFragmentRoots = new ArrayList<FragmentDescriptor>();
54 protected final Map<String,FragmentDescriptor> _webFragmentNameMap = new HashMap<String,FragmentDescriptor>();
55 protected final Map<Resource, FragmentDescriptor> _webFragmentResourceMap = new HashMap<Resource, FragmentDescriptor>();
56 protected final Map<Resource, List<DiscoveredAnnotation>> _annotations = new HashMap<Resource, List<DiscoveredAnnotation>>();
57 protected final List<Resource> _webInfClasses = new ArrayList<Resource>();
58 protected final List<Resource> _webInfJars = new ArrayList<Resource>();
59 protected final List<Resource> _orderedContainerResources = new ArrayList<Resource>();
60 protected final List<Resource> _orderedWebInfResources = new ArrayList<Resource>();
61 protected Ordering _ordering;
62 protected boolean allowDuplicateFragmentNames = false;
63
64 public static class OriginInfo
65 {
66 private final String name;
67 private final Origin origin;
68 private final Descriptor descriptor;
69 private final Annotation annotation;
70 private final Class<?> annotated;
71
72 public OriginInfo (String n, Annotation a,Class<?> ac)
73 {
74 name=n;
75 origin=Origin.Annotation;
76 descriptor=null;
77 annotation=a;
78 annotated=ac;
79 }
80
81 public OriginInfo (String n, Descriptor d)
82 {
83 name = n;
84 descriptor = d;
85 annotation=null;
86 annotated=null;
87 if (d == null)
88 throw new IllegalArgumentException("No descriptor");
89 if (d instanceof FragmentDescriptor)
90 origin = Origin.WebFragment;
91 else if (d instanceof OverrideDescriptor)
92 origin = Origin.WebOverride;
93 else if (d instanceof DefaultsDescriptor)
94 origin = Origin.WebDefaults;
95 else
96 origin = Origin.WebXml;
97 }
98
99 public OriginInfo(String n)
100 {
101 name = n;
102 origin = Origin.API;
103 annotation=null;
104 descriptor=null;
105 annotated=null;
106 }
107
108 public String getName()
109 {
110 return name;
111 }
112
113 public Origin getOriginType()
114 {
115 return origin;
116 }
117
118 public Descriptor getDescriptor()
119 {
120 return descriptor;
121 }
122
123 public String toString()
124 {
125 if (descriptor!=null)
126 return descriptor.toString();
127 if (annotation!=null)
128 return "@"+annotation.annotationType().getSimpleName()+" on "+annotated.getName();
129 return origin.toString();
130 }
131 }
132
133 public MetaData ()
134 {
135 }
136
137
138
139
140 public void clear ()
141 {
142 _webDefaultsRoot = null;
143 _origins.clear();
144 _webXmlRoot = null;
145 _webOverrideRoots.clear();
146 _metaDataComplete = false;
147 _annotations.clear();
148 _descriptorProcessors.clear();
149 _webFragmentRoots.clear();
150 _webFragmentNameMap.clear();
151 _webFragmentResourceMap.clear();
152 _annotations.clear();
153 _webInfJars.clear();
154 _orderedWebInfResources.clear();
155 _orderedContainerResources.clear();
156 _ordering = null;
157 allowDuplicateFragmentNames = false;
158 }
159
160 public void setDefaults (Resource webDefaults)
161 throws Exception
162 {
163 _webDefaultsRoot = new DefaultsDescriptor(webDefaults);
164 _webDefaultsRoot.parse();
165 if (_webDefaultsRoot.isOrdered())
166 {
167 Ordering ordering = getOrdering();
168 if (ordering == null)
169 ordering = new Ordering.AbsoluteOrdering(this);
170
171 List<String> order = _webDefaultsRoot.getOrdering();
172 for (String s:order)
173 {
174 if (s.equalsIgnoreCase("others"))
175 ((Ordering.AbsoluteOrdering)ordering).addOthers();
176 else
177 ((Ordering.AbsoluteOrdering)ordering).add(s);
178 }
179
180
181 setOrdering(ordering);
182 }
183 }
184
185 public void setWebXml (Resource webXml)
186 throws Exception
187 {
188 _webXmlRoot = new WebDescriptor(webXml);
189 _webXmlRoot.parse();
190 _metaDataComplete=_webXmlRoot.getMetaDataComplete() == MetaDataComplete.True;
191
192 if (_webXmlRoot.isOrdered())
193 {
194 Ordering ordering = getOrdering();
195 if (ordering == null)
196 ordering = new Ordering.AbsoluteOrdering(this);
197
198 List<String> order = _webXmlRoot.getOrdering();
199 for (String s:order)
200 {
201 if (s.equalsIgnoreCase("others"))
202 ((Ordering.AbsoluteOrdering)ordering).addOthers();
203 else
204 ((Ordering.AbsoluteOrdering)ordering).add(s);
205 }
206
207
208 setOrdering(ordering);
209 }
210 }
211
212 public void addOverride (Resource override)
213 throws Exception
214 {
215 OverrideDescriptor webOverrideRoot = new OverrideDescriptor(override);
216 webOverrideRoot.setValidating(false);
217 webOverrideRoot.parse();
218
219 switch(webOverrideRoot.getMetaDataComplete())
220 {
221 case True:
222 _metaDataComplete=true;
223 break;
224 case False:
225 _metaDataComplete=false;
226 break;
227 case NotSet:
228 break;
229 }
230
231 if (webOverrideRoot.isOrdered())
232 {
233 Ordering ordering = getOrdering();
234
235 if (ordering == null)
236 ordering = new Ordering.AbsoluteOrdering(this);
237
238 List<String> order = webOverrideRoot.getOrdering();
239 for (String s:order)
240 {
241 if (s.equalsIgnoreCase("others"))
242 ((Ordering.AbsoluteOrdering)ordering).addOthers();
243 else
244 ((Ordering.AbsoluteOrdering)ordering).add(s);
245 }
246
247
248 setOrdering(ordering);
249 }
250 _webOverrideRoots.add(webOverrideRoot);
251 }
252
253
254
255
256
257
258
259
260
261 public void addFragment (Resource jarResource, Resource xmlResource)
262 throws Exception
263 {
264 if (_metaDataComplete)
265 return;
266
267
268 FragmentDescriptor descriptor = new FragmentDescriptor(xmlResource);
269 _webFragmentResourceMap.put(jarResource, descriptor);
270 _webFragmentRoots.add(descriptor);
271
272 descriptor.parse();
273
274 if (descriptor.getName() != null)
275 {
276 Descriptor existing = _webFragmentNameMap.get(descriptor.getName());
277 if (existing != null && !isAllowDuplicateFragmentNames())
278 {
279 throw new IllegalStateException("Duplicate fragment name: "+descriptor.getName()+" for "+existing.getResource()+" and "+descriptor.getResource());
280 }
281 else
282 _webFragmentNameMap.put(descriptor.getName(), descriptor);
283 }
284
285
286
287 if (_ordering == null && descriptor.isOrdered())
288 {
289 setOrdering(new Ordering.RelativeOrdering(this));
290 return;
291 }
292
293
294 orderFragments();
295 }
296
297
298
299
300
301
302 public void addDiscoveredAnnotations(List<DiscoveredAnnotation> annotations)
303 {
304 if (annotations == null)
305 return;
306 for (DiscoveredAnnotation a:annotations)
307 {
308 addDiscoveredAnnotation(a);
309 }
310 }
311
312
313
314
315
316
317
318
319
320
321
322 public synchronized void addDiscoveredAnnotation (DiscoveredAnnotation annotation)
323 {
324 if (annotation == null)
325 return;
326
327
328
329 Resource resource = annotation.getResource();
330 if (resource == null || !_webInfJars.contains(resource))
331 resource = EmptyResource.INSTANCE;
332
333 List<DiscoveredAnnotation> list = _annotations.get(resource);
334 if (list == null)
335 {
336 list = new ArrayList<DiscoveredAnnotation>();
337 _annotations.put(resource, list);
338 }
339 list.add(annotation);
340 }
341
342
343 public void addDescriptorProcessor(DescriptorProcessor p)
344 {
345 _descriptorProcessors.add(p);
346 }
347
348 public void removeDescriptorProcessor(DescriptorProcessor p)
349 {
350 _descriptorProcessors.remove(p);
351 }
352
353
354 public void orderFragments ()
355 {
356 _orderedWebInfResources.clear();
357 if (getOrdering() != null)
358 _orderedWebInfResources.addAll(getOrdering().order(_webInfJars));
359 }
360
361
362
363
364
365
366
367
368 public void resolve (WebAppContext context)
369 throws Exception
370 {
371 LOG.debug("metadata resolve {}",context);
372
373
374 _origins.clear();
375
376
377 List<Resource> orderedWebInfJars = null;
378 if (getOrdering() != null)
379 {
380 orderedWebInfJars = getOrderedWebInfJars();
381 List<String> orderedLibs = new ArrayList<String>();
382 for (Resource webInfJar:orderedWebInfJars)
383 {
384
385 String fullname = webInfJar.getName();
386 int i = fullname.indexOf(".jar");
387 int j = fullname.lastIndexOf("/", i);
388 orderedLibs.add(fullname.substring(j+1,i+4));
389 }
390 context.setAttribute(ServletContext.ORDERED_LIBS, orderedLibs);
391 }
392
393
394 if (_webXmlRoot != null)
395 {
396 context.getServletContext().setEffectiveMajorVersion(_webXmlRoot.getMajorVersion());
397 context.getServletContext().setEffectiveMinorVersion(_webXmlRoot.getMinorVersion());
398 }
399
400 for (DescriptorProcessor p:_descriptorProcessors)
401 {
402 p.process(context,getWebDefault());
403 p.process(context,getWebXml());
404 for (WebDescriptor wd : getOverrideWebs())
405 {
406 LOG.debug("process {} {}",context,wd);
407 p.process(context,wd);
408 }
409 }
410
411
412
413 List<DiscoveredAnnotation> nonFragAnnotations = _annotations.get(NON_FRAG_RESOURCE);
414 if (nonFragAnnotations != null)
415 {
416 for (DiscoveredAnnotation a:nonFragAnnotations)
417 {
418 LOG.debug("apply {}",a);
419 a.apply();
420 }
421 }
422
423
424
425 List<Resource> resources = null;
426
427 if (getOrdering() != null)
428 resources = orderedWebInfJars;
429 else
430 resources = getWebInfJars();
431
432 for (Resource r:resources)
433 {
434 FragmentDescriptor fd = _webFragmentResourceMap.get(r);
435 if (fd != null)
436 {
437 for (DescriptorProcessor p:_descriptorProcessors)
438 {
439 LOG.debug("process {} {}",context,fd);
440 p.process(context,fd);
441 }
442 }
443
444 List<DiscoveredAnnotation> fragAnnotations = _annotations.get(r);
445 if (fragAnnotations != null)
446 {
447 for (DiscoveredAnnotation a:fragAnnotations)
448 {
449 LOG.debug("apply {}",a);
450 a.apply();
451 }
452 }
453 }
454
455 }
456
457 public boolean isDistributable ()
458 {
459 boolean distributable = (
460 (_webDefaultsRoot != null && _webDefaultsRoot.isDistributable())
461 || (_webXmlRoot != null && _webXmlRoot.isDistributable()));
462
463 for (WebDescriptor d : _webOverrideRoots)
464 distributable&=d.isDistributable();
465
466 if (getOrdering() != null)
467 {
468 List<Resource> orderedResources = getOrderedWebInfJars();
469 for (Resource r: orderedResources)
470 {
471 FragmentDescriptor d = _webFragmentResourceMap.get(r);
472 if (d!=null)
473 distributable = distributable && d.isDistributable();
474 }
475 }
476 return distributable;
477 }
478
479
480 public WebDescriptor getWebXml ()
481 {
482 return _webXmlRoot;
483 }
484
485 public List<WebDescriptor> getOverrideWebs ()
486 {
487 return _webOverrideRoots;
488 }
489
490 public WebDescriptor getWebDefault ()
491 {
492 return _webDefaultsRoot;
493 }
494
495 public List<FragmentDescriptor> getFragments ()
496 {
497 return _webFragmentRoots;
498 }
499
500 public List<Resource> getOrderedWebInfJars()
501 {
502 return _orderedWebInfResources;
503 }
504
505 public List<FragmentDescriptor> getOrderedFragments ()
506 {
507 List<FragmentDescriptor> list = new ArrayList<FragmentDescriptor>();
508 if (getOrdering() == null)
509 return list;
510
511 for (Resource r:getOrderedWebInfJars())
512 {
513 FragmentDescriptor fd = _webFragmentResourceMap.get(r);
514 if (fd != null)
515 list.add(fd);
516 }
517 return list;
518 }
519
520 public Ordering getOrdering()
521 {
522 return _ordering;
523 }
524
525 public void setOrdering (Ordering o)
526 {
527 _ordering = o;
528 orderFragments();
529 }
530
531 public FragmentDescriptor getFragment (Resource jar)
532 {
533 return _webFragmentResourceMap.get(jar);
534 }
535
536 public FragmentDescriptor getFragment(String name)
537 {
538 return _webFragmentNameMap.get(name);
539 }
540
541 public Resource getJarForFragment (String name)
542 {
543 FragmentDescriptor f = getFragment(name);
544 if (f == null)
545 return null;
546
547 Resource jar = null;
548 for (Resource r: _webFragmentResourceMap.keySet())
549 {
550 if (_webFragmentResourceMap.get(r).equals(f))
551 jar = r;
552 }
553 return jar;
554 }
555
556 public Map<String,FragmentDescriptor> getNamedFragments ()
557 {
558 return Collections.unmodifiableMap(_webFragmentNameMap);
559 }
560
561
562 public Origin getOrigin (String name)
563 {
564 OriginInfo x = _origins.get(name);
565 if (x == null)
566 return Origin.NotSet;
567
568 return x.getOriginType();
569 }
570
571 public OriginInfo getOriginInfo (String name)
572 {
573 OriginInfo x = _origins.get(name);
574 if (x == null)
575 return null;
576
577 return x;
578 }
579
580 public Descriptor getOriginDescriptor (String name)
581 {
582 OriginInfo o = _origins.get(name);
583 if (o == null)
584 return null;
585 return o.getDescriptor();
586 }
587
588 public void setOrigin (String name, Descriptor d)
589 {
590 OriginInfo x = new OriginInfo (name, d);
591 _origins.put(name, x);
592 }
593
594 public void setOrigin (String name, Annotation annotation, Class<?> annotated)
595 {
596 if (name == null)
597 return;
598
599 OriginInfo x = new OriginInfo (name, annotation, annotated);
600 _origins.put(name, x);
601 }
602
603 public void setOriginAPI(String name)
604 {
605 if (name == null)
606 return;
607
608 OriginInfo x = new OriginInfo (name);
609 _origins.put(name, x);
610 }
611
612 public boolean isMetaDataComplete()
613 {
614 return _metaDataComplete;
615 }
616
617
618 public void addWebInfJar(Resource newResource)
619 {
620 _webInfJars.add(newResource);
621 }
622
623 public List<Resource> getWebInfJars()
624 {
625 return Collections.unmodifiableList(_webInfJars);
626 }
627
628 public List<Resource> getContainerResources()
629 {
630 return _orderedContainerResources;
631 }
632
633 public void addContainerResource(Resource jar)
634 {
635 _orderedContainerResources.add(jar);
636 }
637
638 public void setWebInfClassesDirs (List<Resource> dirs)
639 {
640 _webInfClasses.addAll(dirs);
641 }
642
643 public List<Resource> getWebInfClassesDirs ()
644 {
645 return _webInfClasses;
646 }
647
648 public boolean isAllowDuplicateFragmentNames()
649 {
650 return allowDuplicateFragmentNames;
651 }
652
653 public void setAllowDuplicateFragmentNames(boolean allowDuplicateFragmentNames)
654 {
655 this.allowDuplicateFragmentNames = allowDuplicateFragmentNames;
656 }
657
658 public Map<String,OriginInfo> getOrigins()
659 {
660 return Collections.unmodifiableMap(_origins);
661 }
662 }