Author: remy.maucherat(a)jboss.com
Date: 2009-05-13 19:10:37 -0400 (Wed, 13 May 2009)
New Revision: 1051
Modified:
trunk/java/org/apache/catalina/startup/ContextConfig.java
trunk/java/org/apache/catalina/startup/LocalStrings.properties
trunk/java/org/apache/catalina/startup/OrderingResolver.java
Log:
- Add WIP relative ordering impl. Now need to test and fix it (arrrr ...).
Modified: trunk/java/org/apache/catalina/startup/ContextConfig.java
===================================================================
--- trunk/java/org/apache/catalina/startup/ContextConfig.java 2009-05-12 07:00:11 UTC (rev
1050)
+++ trunk/java/org/apache/catalina/startup/ContextConfig.java 2009-05-13 23:10:37 UTC (rev
1051)
@@ -1083,7 +1083,12 @@
}
} else if (orderings.size() > 0) {
// Resolve relative ordering
- OrderingResolver.resolveOrder(orderings, order);
+ try {
+ OrderingResolver.resolveOrder(orderings, order);
+ } catch (IllegalStateException e) {
+ log.error(e.getMessage(), e);
+ ok = false;
+ }
} else {
// No order specified
order.addAll(jarsSet);
Modified: trunk/java/org/apache/catalina/startup/LocalStrings.properties
===================================================================
--- trunk/java/org/apache/catalina/startup/LocalStrings.properties 2009-05-12 07:00:11 UTC
(rev 1050)
+++ trunk/java/org/apache/catalina/startup/LocalStrings.properties 2009-05-13 23:10:37 UTC
(rev 1051)
@@ -82,3 +82,8 @@
userConfig.error=Error deploying web application for user {0}
userConfig.start=UserConfig: Processing START
userConfig.stop=UserConfig: Processing STOP
+
+ordering.afterAndBeforeOthers=Jar fragment {0} contains an invalid ordering specifying
both after and before other fragments
+ordering.duplicateName=Jar fragment {0} declares a duplicate name
+ordering.unkonwnName=Jar fragment {0} ordering refers to an unknown fragment name
+ordering.orderConflict=Jar fragment {0} causes an order conflict
Modified: trunk/java/org/apache/catalina/startup/OrderingResolver.java
===================================================================
--- trunk/java/org/apache/catalina/startup/OrderingResolver.java 2009-05-12 07:00:11 UTC
(rev 1050)
+++ trunk/java/org/apache/catalina/startup/OrderingResolver.java 2009-05-13 23:10:37 UTC
(rev 1051)
@@ -24,10 +24,13 @@
package org.apache.catalina.startup;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.Set;
import org.apache.catalina.deploy.WebOrdering;
+import org.apache.catalina.util.StringManager;
/**
* Resolves the relative ordering of web fragments. This is in a separate class
@@ -37,12 +40,126 @@
*/
public class OrderingResolver {
- protected class Ordering {
+ protected static org.jboss.logging.Logger log =
+ org.jboss.logging.Logger.getLogger(OrderingResolver.class);
+
+ /**
+ * The string resources for this package.
+ */
+ protected static final StringManager sm =
+ StringManager.getManager(Constants.Package);
+
+ protected static class Ordering {
protected WebOrdering ordering;
- protected List<WebOrdering> after = new ArrayList<WebOrdering>();
- protected List<WebOrdering> before = new ArrayList<WebOrdering>();
+ protected Set<Ordering> after = new HashSet<Ordering>();
+ protected Set<Ordering> before = new HashSet<Ordering>();
protected boolean afterOthers = false;
protected boolean beforeOthers = false;
+
+ public boolean validate() {
+ try {
+ isBefore(new Ordering());
+ isAfter(new Ordering());
+ } catch (IllegalStateException e) {
+ return false;
+ }
+ return true;
+ }
+
+ public boolean isBefore(Ordering ordering) {
+ Set<Ordering> checked = new HashSet<Ordering>();
+ return isBeforeInternal(ordering, checked);
+ }
+
+ protected boolean isBeforeInternal(Ordering ordering, Set<Ordering>
checked) {
+ checked.add(this);
+ if (before.contains(ordering)) {
+ return true;
+ }
+ Iterator<Ordering> beforeIterator = before.iterator();
+ while (beforeIterator.hasNext()) {
+ Ordering check = beforeIterator.next();
+ if (checked.contains(check)) {
+ throw new IllegalStateException();
+ }
+ if (check.isBeforeInternal(ordering, checked)) {
+ return false;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Check (recursively) if a fragment is after the specified fragment.
+ *
+ * @param ordering
+ * @return
+ */
+ public boolean isAfter(Ordering ordering) {
+ Set<Ordering> checked = new HashSet<Ordering>();
+ return isAfterInternal(ordering, checked);
+ }
+
+ protected boolean isAfterInternal(Ordering ordering, Set<Ordering> checked)
{
+ checked.add(this);
+ if (after.contains(ordering)) {
+ return true;
+ }
+ Iterator<Ordering> afterIterator = after.iterator();
+ while (afterIterator.hasNext()) {
+ Ordering check = afterIterator.next();
+ if (checked.contains(check)) {
+ throw new IllegalStateException();
+ }
+ if (check.isAfterInternal(ordering, checked)) {
+ return false;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Check is a fragment marked as before others is after a fragment that is not.
+ *
+ * @return true if a fragment marked as before others is after a fragment that is
not
+ */
+ public boolean isLastBeforeOthers() {
+ if (!beforeOthers) {
+ throw new IllegalStateException();
+ }
+ Iterator<Ordering> beforeIterator = before.iterator();
+ while (beforeIterator.hasNext()) {
+ Ordering check = beforeIterator.next();
+ if (!check.beforeOthers) {
+ return true;
+ } else if (check.isLastBeforeOthers()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Check is a fragment marked as after others is before a fragment that is not.
+ *
+ * @return true if a fragment marked as after others is before a fragment that is
not
+ */
+ public boolean isFirstAfterOthers() {
+ if (!afterOthers) {
+ throw new IllegalStateException();
+ }
+ Iterator<Ordering> afterIterator = after.iterator();
+ while (afterIterator.hasNext()) {
+ Ordering check = afterIterator.next();
+ if (!check.afterOthers) {
+ return true;
+ } else if (check.isFirstAfterOthers()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
}
/**
@@ -52,7 +169,153 @@
* @param order The generated order list
*/
public static void resolveOrder(List<WebOrdering> webOrderings,
List<String> order) {
+ List<Ordering> work = new ArrayList<Ordering>();
+ // Populate the work Ordering list
+ Iterator<WebOrdering> webOrderingsIterator = webOrderings.iterator();
+ while (webOrderingsIterator.hasNext()) {
+ WebOrdering webOrdering = webOrderingsIterator.next();
+ Ordering ordering = new Ordering();
+ ordering.ordering = webOrdering;
+ ordering.afterOthers = webOrdering.isAfterOthers();
+ ordering.beforeOthers = webOrdering.isBeforeOthers();
+ if (ordering.afterOthers && ordering.beforeOthers) {
+ // Cannot be both after and before others
+ throw new
IllegalStateException(sm.getString("ordering.afterAndBeforeOthers",
webOrdering.getJar()));
+ }
+ work.add(ordering);
+ }
+
+ // Create double linked relationships between the orderings,
+ // and resolve names
+ Iterator<Ordering> workIterator = work.iterator();
+ while (workIterator.hasNext()) {
+ Ordering ordering = workIterator.next();
+ WebOrdering webOrdering = ordering.ordering;
+ Iterator<String> after = webOrdering.getAfter().iterator();
+ while (after.hasNext()) {
+ String name = after.next();
+ Iterator<Ordering> workIterator2 = work.iterator();
+ boolean found = false;
+ while (workIterator2.hasNext()) {
+ Ordering ordering2 = workIterator.next();
+ if (name.equals(ordering2.ordering.getName())) {
+ if (found) {
+ // Duplicate name
+ throw new
IllegalStateException(sm.getString("ordering.duplicateName",
webOrdering.getJar()));
+ }
+ ordering.after.add(ordering2);
+ ordering2.before.add(ordering);
+ found = true;
+ }
+ }
+ if (!found) {
+ // Unknown name
+ throw new
IllegalStateException(sm.getString("ordering.unkonwnName",
webOrdering.getJar()));
+ }
+ }
+ Iterator<String> before = webOrdering.getAfter().iterator();
+ while (before.hasNext()) {
+ String name = before.next();
+ Iterator<Ordering> workIterator2 = work.iterator();
+ boolean found = false;
+ while (workIterator2.hasNext()) {
+ Ordering ordering2 = workIterator.next();
+ if (name.equals(ordering2.ordering.getName())) {
+ if (found) {
+ // Duplicate name
+ throw new
IllegalStateException(sm.getString("ordering.duplicateName",
webOrdering.getJar()));
+ }
+ ordering.before.add(ordering2);
+ ordering2.after.add(ordering);
+ found = true;
+ }
+ }
+ if (!found) {
+ // Unknown name
+ throw new
IllegalStateException(sm.getString("ordering.unkonwnName",
webOrdering.getJar()));
+ }
+ }
+ }
+
+ // Validate ordering
+ workIterator = work.iterator();
+ while (workIterator.hasNext()) {
+ workIterator.next().validate();
+ }
+
+ // Create three ordered lists that will then be merged
+ List<Ordering> tempOrder = new ArrayList<Ordering>();
+
+ // Create the ordered list of fragments which are before others
+ workIterator = work.iterator();
+ while (workIterator.hasNext()) {
+ Ordering ordering = workIterator.next();
+ if (ordering.beforeOthers) {
+ // Insert at the first possible position
+ int insertAfter = -1;
+ boolean last = ordering.isLastBeforeOthers();
+ int lastBeforeOthers = -1;
+ for (int i = 0; i < tempOrder.size(); i++) {
+ if (ordering.isAfter(tempOrder.get(i))) {
+ insertAfter = i;
+ }
+ if (tempOrder.get(i).beforeOthers) {
+ lastBeforeOthers = i;
+ }
+ }
+ int pos = insertAfter;
+ if (last && lastBeforeOthers > insertAfter) {
+ pos = lastBeforeOthers;
+ }
+ tempOrder.add(pos + 1, ordering);
+ } else if (ordering.afterOthers) {
+ // Insert at the last possible element
+ int insertBefore = tempOrder.size() - 1;
+ boolean first = ordering.isFirstAfterOthers();
+ int firstAfterOthers = tempOrder.size() - 1;
+ for (int i = tempOrder.size() - 1; i >= 0; i--) {
+ if (ordering.isBefore(tempOrder.get(i))) {
+ insertBefore = i;
+ }
+ if (tempOrder.get(i).afterOthers) {
+ firstAfterOthers = i;
+ }
+ }
+ int pos = insertBefore;
+ if (first && firstAfterOthers < insertBefore) {
+ pos = firstAfterOthers;
+ }
+ tempOrder.add(pos, ordering);
+ } else {
+ // Insert according to other already inserted elements
+ int insertAfter = -1;
+ int insertBefore = tempOrder.size() - 1;
+ for (int i = 0; i < tempOrder.size(); i++) {
+ if (ordering.isAfter(tempOrder.get(i)) ||
tempOrder.get(i).beforeOthers) {
+ insertAfter = i;
+ }
+ if (ordering.isBefore(tempOrder.get(i)) ||
tempOrder.get(i).afterOthers) {
+ insertBefore = i;
+ }
+ }
+ if (insertAfter > insertBefore) {
+ // Conflicting order (probably caught earlier)
+ throw new
IllegalStateException(sm.getString("ordering.orderConflict",
ordering.ordering.getJar()));
+ }
+ // Insert somewhere in the range
+ tempOrder.add(insertAfter + 1, ordering);
+ }
+ }
+
+ // Create the final ordered list
+ Iterator<Ordering> tempOrderIterator = tempOrder.iterator();
+ while (tempOrderIterator.hasNext()) {
+ Ordering ordering = tempOrderIterator.next();
+ order.add(ordering.ordering.getJar());
+ }
+
}
+
}
Show replies by date