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