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.HashMap;
23 import java.util.Iterator;
24 import java.util.LinkedList;
25 import java.util.List;
26 import java.util.Map;
27
28 import org.eclipse.jetty.util.resource.Resource;
29
30
31
32
33
34 public interface Ordering
35 {
36 public List<Resource> order(List<Resource> fragments);
37 public boolean isAbsolute ();
38 public boolean hasOther();
39
40
41
42
43
44
45 public static class AbsoluteOrdering implements Ordering
46 {
47 public static final String OTHER = "@@-OTHER-@@";
48 protected List<String> _order = new ArrayList<String>();
49 protected boolean _hasOther = false;
50 protected MetaData _metaData;
51
52 public AbsoluteOrdering (MetaData metaData)
53 {
54 _metaData = metaData;
55 }
56
57
58
59
60
61 @Override
62 public List<Resource> order(List<Resource> jars)
63 {
64 List<Resource> orderedList = new ArrayList<Resource>();
65 List<Resource> tmp = new ArrayList<Resource>(jars);
66
67
68
69 Map<String,FragmentDescriptor> others = new HashMap<String,FragmentDescriptor>(_metaData.getNamedFragments());
70
71
72 int index = -1;
73 for (String item:_order)
74 {
75 if (!item.equals(OTHER))
76 {
77 FragmentDescriptor f = others.remove(item);
78 if (f != null)
79 {
80 Resource jar = _metaData.getJarForFragment(item);
81 orderedList.add(jar);
82
83 tmp.remove(jar);
84 }
85 }
86 else
87 index = orderedList.size();
88 }
89
90
91 if (_hasOther)
92 {
93 orderedList.addAll((index < 0? 0: index), tmp);
94 }
95
96 return orderedList;
97 }
98
99 @Override
100 public boolean isAbsolute()
101 {
102 return true;
103 }
104
105 public void add (String name)
106 {
107 _order.add(name);
108 }
109
110 public void addOthers ()
111 {
112 if (_hasOther)
113 throw new IllegalStateException ("Duplicate <other> element in absolute ordering");
114
115 _hasOther = true;
116 _order.add(OTHER);
117 }
118
119 @Override
120 public boolean hasOther ()
121 {
122 return _hasOther;
123 }
124 }
125
126
127
128
129
130 public static class RelativeOrdering implements Ordering
131 {
132 protected MetaData _metaData;
133 protected LinkedList<Resource> _beforeOthers = new LinkedList<Resource>();
134 protected LinkedList<Resource> _afterOthers = new LinkedList<Resource>();
135 protected LinkedList<Resource> _noOthers = new LinkedList<Resource>();
136
137 public RelativeOrdering (MetaData metaData)
138 {
139 _metaData = metaData;
140 }
141
142
143
144
145
146 @Override
147 public List<Resource> order(List<Resource> jars)
148 {
149 _beforeOthers.clear();
150 _afterOthers.clear();
151 _noOthers.clear();
152
153
154 for (Resource jar:jars)
155 {
156
157 FragmentDescriptor descriptor = _metaData.getFragment(jar);
158 if (descriptor != null)
159 {
160 switch (descriptor.getOtherType())
161 {
162 case None:
163 {
164 addNoOthers(jar);
165 break;
166 }
167 case Before:
168 {
169 addBeforeOthers(jar);
170 break;
171 }
172 case After:
173 {
174 addAfterOthers(jar);
175 break;
176 }
177 }
178 }
179 else
180 {
181
182 addNoOthers(jar);
183 }
184 }
185
186
187 List<Resource> orderedList = new ArrayList<Resource>();
188 int maxIterations = 2;
189 boolean done = false;
190 do
191 {
192
193 boolean changesBefore = orderList(_beforeOthers);
194
195
196 boolean changesAfter = orderList(_afterOthers);
197
198
199 boolean changesNone = orderList(_noOthers);
200
201
202 done = (!changesBefore && !changesAfter && !changesNone);
203 }
204 while (!done && (--maxIterations >0));
205
206
207 if (!done)
208 throw new IllegalStateException("Circular references for fragments");
209
210 for (Resource r: _beforeOthers)
211 orderedList.add(r);
212 for (Resource r: _noOthers)
213 orderedList.add(r);
214 for(Resource r: _afterOthers)
215 orderedList.add(r);
216
217 return orderedList;
218 }
219
220 @Override
221 public boolean isAbsolute ()
222 {
223 return false;
224 }
225
226 @Override
227 public boolean hasOther ()
228 {
229 return !_beforeOthers.isEmpty() || !_afterOthers.isEmpty();
230 }
231
232 public void addBeforeOthers (Resource r)
233 {
234 _beforeOthers.addLast(r);
235 }
236
237 public void addAfterOthers (Resource r)
238 {
239 _afterOthers.addLast(r);
240 }
241
242 public void addNoOthers (Resource r)
243 {
244 _noOthers.addLast(r);
245 }
246
247 protected boolean orderList (LinkedList<Resource> list)
248 {
249
250 boolean changes = false;
251 List<Resource> iterable = new ArrayList<Resource>(list);
252 Iterator<Resource> itor = iterable.iterator();
253
254 while (itor.hasNext())
255 {
256 Resource r = itor.next();
257 FragmentDescriptor f = _metaData.getFragment(r);
258 if (f == null)
259 {
260
261 continue;
262 }
263
264
265 List<String> befores = f.getBefores();
266 if (befores != null && !befores.isEmpty())
267 {
268 for (String b: befores)
269 {
270
271
272
273 if (!isBefore(list, f.getName(), b))
274 {
275
276 int idx1 = getIndexOf(list, f.getName());
277 int idx2 = getIndexOf(list, b);
278
279
280 if (idx2 < 0)
281 {
282 changes = true;
283
284 Resource bResource = _metaData.getJarForFragment(b);
285 if (bResource != null)
286 {
287
288 if (_noOthers.remove(bResource))
289 {
290 insert(list, idx1+1, b);
291
292 }
293 }
294 }
295 else
296 {
297
298 list.remove(idx1);
299 insert(list, idx2, f.getName());
300 changes = true;
301 }
302 }
303 }
304 }
305
306
307 List<String> afters = f.getAfters();
308 if (afters != null && !afters.isEmpty())
309 {
310 for (String a: afters)
311 {
312
313 if (!isAfter(list, f.getName(), a))
314 {
315
316 int idx1 = getIndexOf(list, f.getName());
317 int idx2 = getIndexOf(list, a);
318
319
320 if (idx2 < 0)
321 {
322 changes = true;
323
324 Resource aResource = _metaData.getJarForFragment(a);
325 if (aResource != null)
326 {
327 if (_noOthers.remove(aResource))
328 {
329 insert(list,idx1, aResource);
330 }
331 }
332 }
333 else
334 {
335
336 list.remove(idx2);
337 insert(list,idx1, a);
338 changes = true;
339 }
340 }
341
342
343
344 }
345 }
346 }
347
348 return changes;
349 }
350
351
352
353
354
355
356
357
358
359 protected boolean isBefore (List<Resource> list, String fragNameA, String fragNameB)
360 {
361
362
363 int idxa = getIndexOf(list, fragNameA);
364 int idxb = getIndexOf(list, fragNameB);
365
366
367 if (idxb >=0 && idxb < idxa)
368 {
369
370 return false;
371 }
372
373 if (idxb < 0)
374 {
375
376
377 if (list == _beforeOthers)
378 {
379
380
381 return true;
382 }
383 else if (list == _afterOthers)
384 {
385
386
387 if (_beforeOthers.contains(fragNameB))
388 throw new IllegalStateException("Incorrect relationship: "+fragNameA+" before "+fragNameB);
389 else
390 return false;
391 }
392 }
393
394
395 return true;
396 }
397
398
399
400
401
402
403
404
405
406
407 protected boolean isAfter(List<Resource> list, String fragNameA, String fragNameB)
408 {
409 int idxa = getIndexOf(list, fragNameA);
410 int idxb = getIndexOf(list, fragNameB);
411
412 if (idxb >=0 && idxa < idxb)
413 {
414
415 return false;
416 }
417
418 if (idxb < 0)
419 {
420
421
422 if (list == _afterOthers)
423 {
424
425
426 return true;
427 }
428 else if (list == _beforeOthers)
429 {
430
431
432 if (_afterOthers.contains(fragNameB))
433 throw new IllegalStateException("Incorrect relationship: "+fragNameB+" after "+fragNameA);
434 else
435 return false;
436 }
437 }
438
439 return true;
440 }
441
442
443
444
445
446
447
448
449
450 protected void insert(List<Resource> list, int index, String fragName)
451 {
452 Resource jar = _metaData.getJarForFragment(fragName);
453 if (jar == null)
454 throw new IllegalStateException("No jar for insertion");
455
456 insert(list, index, jar);
457 }
458
459 protected void insert(List<Resource> list, int index, Resource resource)
460 {
461 if (list == null)
462 throw new IllegalStateException("List is null for insertion");
463
464
465 if (index > list.size())
466 list.add(resource);
467 else
468 list.add(index, resource);
469 }
470
471 protected void remove (List<Resource> resources, Resource r)
472 {
473 if (resources == null)
474 return;
475 resources.remove(r);
476 }
477
478 protected int getIndexOf(List<Resource> resources, String fragmentName)
479 {
480 FragmentDescriptor fd = _metaData.getFragment(fragmentName);
481 if (fd == null)
482 return -1;
483
484
485 Resource r = _metaData.getJarForFragment(fragmentName);
486 if (r == null)
487 return -1;
488
489 return resources.indexOf(r);
490 }
491 }
492
493 }