Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'jetty-webapp/src/main/java/org/eclipse/jetty/webapp/Ordering.java')
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/Ordering.java464
1 files changed, 1 insertions, 463 deletions
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/Ordering.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/Ordering.java
index 8d9aff972c..4ffd6d9d6f 100644
--- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/Ordering.java
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/Ordering.java
@@ -18,476 +18,14 @@
package org.eclipse.jetty.webapp;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
import java.util.List;
-import java.util.Map;
import org.eclipse.jetty.util.resource.Resource;
-
/**
* Ordering options for jars in WEB-INF lib.
*/
public interface Ordering
{
- public List<Resource> order(List<Resource> fragments);
- public boolean isAbsolute ();
- public boolean hasOther();
-
- /**
- * AbsoluteOrdering
- *
- * An &lt;absolute-order&gt; element in web.xml
- */
- public static class AbsoluteOrdering implements Ordering
- {
- public static final String OTHER = "@@-OTHER-@@";
- protected List<String> _order = new ArrayList<String>();
- protected boolean _hasOther = false;
- protected MetaData _metaData;
-
- public AbsoluteOrdering (MetaData metaData)
- {
- _metaData = metaData;
- }
-
- /**
- * Order the list of jars in WEB-INF/lib according to the ordering declarations in the descriptors
- * @see org.eclipse.jetty.webapp.Ordering#order(java.util.List)
- */
- @Override
- public List<Resource> order(List<Resource> jars)
- {
- List<Resource> orderedList = new ArrayList<Resource>();
- List<Resource> tmp = new ArrayList<Resource>(jars);
-
- //1. put everything into the list of named others, and take the named ones out of there,
- //assuming we will want to use the <other> clause
- Map<String,FragmentDescriptor> others = new HashMap<String,FragmentDescriptor>(_metaData.getNamedFragments());
-
- //2. for each name, take out of the list of others, add to tail of list
- int index = -1;
- for (String item:_order)
- {
- if (!item.equals(OTHER))
- {
- FragmentDescriptor f = others.remove(item);
- if (f != null)
- {
- Resource jar = _metaData.getJarForFragment(item);
- orderedList.add(jar); //take from others and put into final list in order, ignoring duplicate names
- //remove resource from list for resource matching name of descriptor
- tmp.remove(jar);
- }
- }
- else
- index = orderedList.size(); //remember the index at which we want to add in all the others
- }
-
- //3. if <other> was specified, insert rest of the fragments
- if (_hasOther)
- {
- orderedList.addAll((index < 0? 0: index), tmp);
- }
-
- return orderedList;
- }
-
- @Override
- public boolean isAbsolute()
- {
- return true;
- }
-
- public void add (String name)
- {
- _order.add(name);
- }
-
- public void addOthers ()
- {
- if (_hasOther)
- throw new IllegalStateException ("Duplicate <other> element in absolute ordering");
-
- _hasOther = true;
- _order.add(OTHER);
- }
-
- @Override
- public boolean hasOther ()
- {
- return _hasOther;
- }
- }
- /**
- * RelativeOrdering
- *
- * A set of &lt;order&gt; elements in web-fragment.xmls.
- */
- public static class RelativeOrdering implements Ordering
- {
- protected MetaData _metaData;
- protected LinkedList<Resource> _beforeOthers = new LinkedList<Resource>();
- protected LinkedList<Resource> _afterOthers = new LinkedList<Resource>();
- protected LinkedList<Resource> _noOthers = new LinkedList<Resource>();
-
- public RelativeOrdering (MetaData metaData)
- {
- _metaData = metaData;
- }
- /**
- * Order the list of jars according to the ordering declared
- * in the various web-fragment.xml files.
- * @see org.eclipse.jetty.webapp.Ordering#order(java.util.List)
- */
- @Override
- public List<Resource> order(List<Resource> jars)
- {
- _beforeOthers.clear();
- _afterOthers.clear();
- _noOthers.clear();
-
- //for each jar, put it into the ordering according to the fragment ordering
- for (Resource jar:jars)
- {
- //check if the jar has a fragment descriptor
- FragmentDescriptor descriptor = _metaData.getFragment(jar);
- if (descriptor != null)
- {
- switch (descriptor.getOtherType())
- {
- case None:
- {
- addNoOthers(jar);
- break;
- }
- case Before:
- {
- addBeforeOthers(jar);
- break;
- }
- case After:
- {
- addAfterOthers(jar);
- break;
- }
- }
- }
- else
- {
- //jar fragment has no descriptor, but there is a relative ordering in place, so it must be part of the others
- addNoOthers(jar);
- }
- }
-
- //now apply the ordering
- List<Resource> orderedList = new ArrayList<Resource>();
- int maxIterations = 2;
- boolean done = false;
- do
- {
- //1. order the before-others according to any explicit before/after relationships
- boolean changesBefore = orderList(_beforeOthers);
-
- //2. order the after-others according to any explicit before/after relationships
- boolean changesAfter = orderList(_afterOthers);
-
- //3. order the no-others according to their explicit before/after relationships
- boolean changesNone = orderList(_noOthers);
-
- //we're finished on a clean pass through with no ordering changes
- done = (!changesBefore && !changesAfter && !changesNone);
- }
- while (!done && (--maxIterations >0));
-
- //4. merge before-others + no-others +after-others
- if (!done)
- throw new IllegalStateException("Circular references for fragments");
-
- for (Resource r: _beforeOthers)
- orderedList.add(r);
- for (Resource r: _noOthers)
- orderedList.add(r);
- for(Resource r: _afterOthers)
- orderedList.add(r);
-
- return orderedList;
- }
-
- @Override
- public boolean isAbsolute ()
- {
- return false;
- }
-
- @Override
- public boolean hasOther ()
- {
- return !_beforeOthers.isEmpty() || !_afterOthers.isEmpty();
- }
-
- public void addBeforeOthers (Resource r)
- {
- _beforeOthers.addLast(r);
- }
-
- public void addAfterOthers (Resource r)
- {
- _afterOthers.addLast(r);
- }
-
- public void addNoOthers (Resource r)
- {
- _noOthers.addLast(r);
- }
-
- protected boolean orderList (LinkedList<Resource> list)
- {
- //Take a copy of the list so we can iterate over it and at the same time do random insertions
- boolean changes = false;
- List<Resource> iterable = new ArrayList<Resource>(list);
- Iterator<Resource> itor = iterable.iterator();
-
- while (itor.hasNext())
- {
- Resource r = itor.next();
- FragmentDescriptor f = _metaData.getFragment(r);
- if (f == null)
- {
- //no fragment for this resource so cannot have any ordering directives
- continue;
- }
-
- //Handle any explicit <before> relationships for the fragment we're considering
- List<String> befores = f.getBefores();
- if (befores != null && !befores.isEmpty())
- {
- for (String b: befores)
- {
- //Fragment we're considering must be before b
- //Check that we are already before it, if not, move us so that we are.
- //If the name does not exist in our list, then get it out of the no-other list
- if (!isBefore(list, f.getName(), b))
- {
- //b is not already before name, move it so that it is
- int idx1 = getIndexOf(list, f.getName());
- int idx2 = getIndexOf(list, b);
-
- //if b is not in the same list
- if (idx2 < 0)
- {
- changes = true;
- // must be in the noOthers list or it would have been an error
- Resource bResource = _metaData.getJarForFragment(b);
- if (bResource != null)
- {
- //If its in the no-others list, insert into this list so that we are before it
- if (_noOthers.remove(bResource))
- {
- insert(list, idx1+1, b);
-
- }
- }
- }
- else
- {
- //b is in the same list but b is before name, so swap it around
- list.remove(idx1);
- insert(list, idx2, f.getName());
- changes = true;
- }
- }
- }
- }
-
- //Handle any explicit <after> relationships
- List<String> afters = f.getAfters();
- if (afters != null && !afters.isEmpty())
- {
- for (String a: afters)
- {
- //Check that fragment we're considering is after a, moving it if possible if its not
- if (!isAfter(list, f.getName(), a))
- {
- //name is not after a, move it
- int idx1 = getIndexOf(list, f.getName());
- int idx2 = getIndexOf(list, a);
-
- //if a is not in the same list as name
- if (idx2 < 0)
- {
- changes = true;
- //take it out of the noOthers list and put it in the right place in this list
- Resource aResource = _metaData.getJarForFragment(a);
- if (aResource != null)
- {
- if (_noOthers.remove(aResource))
- {
- insert(list,idx1, aResource);
- }
- }
- }
- else
- {
- //a is in the same list as name, but in the wrong place, so move it
- list.remove(idx2);
- insert(list,idx1, a);
- changes = true;
- }
- }
- //Name we're considering must be after this name
- //Check we're already after it, if not, move us so that we are.
- //If the name does not exist in our list, then get it out of the no-other list
- }
- }
- }
-
- return changes;
- }
-
- /**
- * Is fragment with name a before fragment with name b?
- *
- * @param list the list of resources
- * @param fragNameA the first fragment
- * @param fragNameB the second fragment
- * @return true if fragment name A is before fragment name B
- */
- protected boolean isBefore (List<Resource> list, String fragNameA, String fragNameB)
- {
- //check if a and b are already in the same list, and b is already
- //before a
- int idxa = getIndexOf(list, fragNameA);
- int idxb = getIndexOf(list, fragNameB);
-
-
- if (idxb >=0 && idxb < idxa)
- {
- //a and b are in the same list but a is not before b
- return false;
- }
-
- if (idxb < 0)
- {
- //a and b are not in the same list, but it is still possible that a is before
- //b, depending on which list we're examining
- if (list == _beforeOthers)
- {
- //The list we're looking at is the beforeOthers.If b is in the _afterOthers or the _noOthers, then by
- //definition a is before it
- return true;
- }
- else if (list == _afterOthers)
- {
- //The list we're looking at is the afterOthers, then a will be the tail of
- //the final list. If b is in the beforeOthers list, then b will be before a and an error.
- if (_beforeOthers.contains(fragNameB))
- throw new IllegalStateException("Incorrect relationship: "+fragNameA+" before "+fragNameB);
- else
- return false; //b could be moved to the list
- }
- }
-
- //a and b are in the same list and a is already before b
- return true;
- }
-
-
- /**
- * Is fragment name "a" after fragment name "b"?
- *
- * @param list the list of resources
- * @param fragNameA the first fragment
- * @param fragNameB the second fragment
- * @return true if fragment name A is after fragment name B
- */
- protected boolean isAfter(List<Resource> list, String fragNameA, String fragNameB)
- {
- int idxa = getIndexOf(list, fragNameA);
- int idxb = getIndexOf(list, fragNameB);
-
- if (idxb >=0 && idxa < idxb)
- {
- //a and b are both in the same list, but a is before b
- return false;
- }
-
- if (idxb < 0)
- {
- //a and b are in different lists. a could still be after b depending on which list it is in.
-
- if (list == _afterOthers)
- {
- //The list we're looking at is the afterOthers. If b is in the beforeOthers or noOthers then
- //by definition a is after b because a is in the afterOthers list.
- return true;
- }
- else if (list == _beforeOthers)
- {
- //The list we're looking at is beforeOthers, and contains a and will be before
- //everything else in the final ist. If b is in the afterOthers list, then a cannot be before b.
- if (_afterOthers.contains(fragNameB))
- throw new IllegalStateException("Incorrect relationship: "+fragNameB+" after "+fragNameA);
- else
- return false; //b could be moved from noOthers list
- }
- }
-
- return true; //a and b in the same list, a is after b
- }
-
- /**
- * Insert the resource matching the fragName into the list of resources
- * at the location indicated by index.
- *
- * @param list the list of resources
- * @param index the index to insert into
- * @param fragName the fragment name to insert
- */
- protected void insert(List<Resource> list, int index, String fragName)
- {
- Resource jar = _metaData.getJarForFragment(fragName);
- if (jar == null)
- throw new IllegalStateException("No jar for insertion");
-
- insert(list, index, jar);
- }
-
- protected void insert(List<Resource> list, int index, Resource resource)
- {
- if (list == null)
- throw new IllegalStateException("List is null for insertion");
-
- //add it at the end
- if (index > list.size())
- list.add(resource);
- else
- list.add(index, resource);
- }
-
- protected void remove (List<Resource> resources, Resource r)
- {
- if (resources == null)
- return;
- resources.remove(r);
- }
-
- protected int getIndexOf(List<Resource> resources, String fragmentName)
- {
- FragmentDescriptor fd = _metaData.getFragment(fragmentName);
- if (fd == null)
- return -1;
-
-
- Resource r = _metaData.getJarForFragment(fragmentName);
- if (r == null)
- return -1;
-
- return resources.indexOf(r);
- }
- }
-
+ public List<Resource> order(List<Resource> fragments);
}

Back to the top