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