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