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