You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by dj...@apache.org on 2005/07/08 22:50:40 UTC

svn commit: r209887 - in /geronimo/trunk/modules: jetty-builder/src/java/org/apache/geronimo/jetty/deployment/ jetty-builder/src/test/org/apache/geronimo/jetty/deployment/ jetty/src/java/org/apache/geronimo/jetty/

Author: djencks
Date: Fri Jul  8 13:50:39 2005
New Revision: 209887

URL: http://svn.apache.org/viewcvs?rev=209887&view=rev
Log:
GERONIMO-645 Respect load-on-startup tags in jetty

Added:
    geronimo/trunk/modules/jetty-builder/src/test/org/apache/geronimo/jetty/deployment/StartupOrderComparatorTest.java
Modified:
    geronimo/trunk/modules/jetty-builder/src/java/org/apache/geronimo/jetty/deployment/JettyModuleBuilder.java
    geronimo/trunk/modules/jetty/src/java/org/apache/geronimo/jetty/JettyServletHolder.java

Modified: geronimo/trunk/modules/jetty-builder/src/java/org/apache/geronimo/jetty/deployment/JettyModuleBuilder.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/jetty-builder/src/java/org/apache/geronimo/jetty/deployment/JettyModuleBuilder.java?rev=209887&r1=209886&r2=209887&view=diff
==============================================================================
--- geronimo/trunk/modules/jetty-builder/src/java/org/apache/geronimo/jetty/deployment/JettyModuleBuilder.java (original)
+++ geronimo/trunk/modules/jetty-builder/src/java/org/apache/geronimo/jetty/deployment/JettyModuleBuilder.java Fri Jul  8 13:50:39 2005
@@ -31,6 +31,7 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -38,6 +39,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeSet;
 import java.util.jar.JarFile;
 import java.util.zip.ZipEntry;
 import javax.management.MalformedObjectNameException;
@@ -731,10 +733,8 @@
             ServletType[] servletTypes = webApp.getServletArray();
             Map portMap = webModule.getPortMap();
 
-            for (int i = 0; i < servletTypes.length; i++) {
-                ServletType servletType = servletTypes[i];
-                addServlet(webModuleName, webModule.getModuleFile(), servletType, servletMappings, securityRoles, rolePermissions, portMap, webClassLoader, moduleJ2eeContext, earContext);
-            }
+            addServlets(webModuleName, webModule.getModuleFile(), servletTypes, servletMappings, securityRoles, rolePermissions, portMap, webClassLoader, moduleJ2eeContext, earContext);
+
             if (jettyWebApp.isSetSecurityRealmName()) {
                 String securityRealmName = jettyWebApp.getSecurityRealmName().trim();
                 webModuleData.setAttribute("securityRealmName", securityRealmName);
@@ -801,8 +801,63 @@
         return webClassLoader;
     }
 
+
+    /**
+     * Adds the provided servlets, taking into account the load-on-startup ordering.
+     *
+     * @param webModuleName an <code>ObjectName</code> value
+     * @param moduleFile a <code>JarFile</code> value
+     * @param servletTypes a <code>ServletType[]</code> value, contains the <code>servlet</code> entries from <code>web.xml</code>.
+     * @param servletMappings a <code>Map</code> value
+     * @param securityRoles a <code>Set</code> value
+     * @param rolePermissions a <code>Map</code> value
+     * @param portMap a <code>Map</code> value
+     * @param webClassLoader a <code>ClassLoader</code> value
+     * @param moduleJ2eeContext a <code>J2eeContext</code> value
+     * @param earContext an <code>EARContext</code> value
+     * @exception MalformedObjectNameException if an error occurs
+     * @exception DeploymentException if an error occurs
+     */
+    private void addServlets(ObjectName webModuleName,
+                            JarFile moduleFile,
+                            ServletType[] servletTypes,
+                            Map servletMappings,
+                            Set securityRoles,
+                            Map rolePermissions, Map portMap,
+                            ClassLoader webClassLoader,
+                            J2eeContext moduleJ2eeContext,
+                            EARContext earContext) throws MalformedObjectNameException, DeploymentException {
+
+        // this TreeSet will order the ServletTypes based on whether
+        // they have a load-on-startup element and what its value is
+        TreeSet loadOrder = new TreeSet(new StartupOrderComparator());
+
+        // add all of the servlets to the sorted set
+        for (int i = 0; i < servletTypes.length; i++) {
+            loadOrder.add(servletTypes[i]);
+        }
+
+        // now that they're sorted, read them in order and add them to
+        // the context.  we'll use a GBean reference to enforce the
+        // load order.  Each servlet GBean (except the first) has a
+        // reference to the previous GBean.  The kernel will ensure
+        // that each "previous" GBean is running before it starts any
+        // other GBeans that reference it.  See also
+        // o.a.g.jetty.JettyFilterMapping which provided the example
+        // of how to do this.
+        // http://issues.apache.org/jira/browse/GERONIMO-645
+        ServletType previousServlet = null;
+        for (Iterator servlets = loadOrder.iterator(); servlets.hasNext(); ) {
+            ServletType servletType = (ServletType)servlets.next();
+            addServlet(webModuleName, moduleFile, previousServlet, servletType, servletMappings, securityRoles, rolePermissions, portMap, webClassLoader, moduleJ2eeContext, earContext);
+            previousServlet = servletType;
+        }
+    }
+
+
     private void addServlet(ObjectName webModuleName,
                             JarFile moduleFile,
+                            ServletType previousServlet,
                             ServletType servletType,
                             Map servletMappings,
                             Set securityRoles,
@@ -852,6 +907,16 @@
         } else {
             throw new DeploymentException("Neither servlet class nor jsp file is set for " + servletName);
         }
+
+        // link to previous servlet, if there is one, so that we
+        // preserve the <load-on-startup> ordering.
+        // http://issues.apache.org/jira/browse/GERONIMO-645
+        if (null != previousServlet) {
+            String name = previousServlet.getServletName().getStringValue().trim();
+            ObjectName oName = NameFactory.getWebComponentName(null, null, null, null, name, NameFactory.SERVLET, moduleJ2eeContext);
+            servletData.setReferencePattern("Previous", oName);
+        }
+
         //TODO in init param setter, add classpath if jspFile is not null.
         servletData.setReferencePattern("JettyServletRegistration", webModuleName);
         servletData.setAttribute("servletName", servletName);
@@ -1287,4 +1352,46 @@
         return GBEAN_INFO;
     }
 
+    static class StartupOrderComparator implements Comparator {
+        /**
+         * comparator that compares first on the basis of startup order, and then on the lexicographical
+         * ordering of servlet name.  Since the servlet names have a uniqueness constraint, this should
+         * provide a total ordering consistent with equals.  All servlets with no startup order are after
+         * all servlets with a startup order.
+         * 
+         * @param o1  first ServletType object
+         * @param o2  second ServletType object
+         * @return an int < 0 if o1 precedes o2, 0 if they are equal, and > 0 if o2 preceeds o1.
+         */
+        public int compare(Object o1, Object o2) {
+            ServletType s1 = (ServletType)o1;
+            ServletType s2 = (ServletType)o2;
+
+            // load-on-startup is set for neither.  the
+            // ordering at this point doesn't matter, but we
+            // should return "0" only if the two objects say
+            // they are equal
+            if (!s1.isSetLoadOnStartup() && !s2.isSetLoadOnStartup()) {
+                return s1.equals(s2) ? 0 : s1.getServletName().getStringValue().trim().compareTo(s2.getServletName().getStringValue().trim());
+            }
+
+            // load-on-startup is set for one but not the
+            // other.  whichever one is set will be "less
+            // than", i.e. it will be loaded first
+            if (s1.isSetLoadOnStartup() && !s2.isSetLoadOnStartup()) {
+                return -1;
+            }
+            if (!s1.isSetLoadOnStartup() && s2.isSetLoadOnStartup()) {
+                return 1;
+            }
+
+            // load-on-startup is set for both.  whichever one
+            // has a smaller value is "less than"
+            int comp = s1.getLoadOnStartup().getBigIntegerValue().compareTo(s2.getLoadOnStartup().getBigIntegerValue());
+            if (comp == 0) {
+                return s1.getServletName().getStringValue().trim().compareTo(s2.getServletName().getStringValue().trim());
+            }
+            return comp;
+        }
+    }
 }

Added: geronimo/trunk/modules/jetty-builder/src/test/org/apache/geronimo/jetty/deployment/StartupOrderComparatorTest.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/jetty-builder/src/test/org/apache/geronimo/jetty/deployment/StartupOrderComparatorTest.java?rev=209887&view=auto
==============================================================================
--- geronimo/trunk/modules/jetty-builder/src/test/org/apache/geronimo/jetty/deployment/StartupOrderComparatorTest.java (added)
+++ geronimo/trunk/modules/jetty-builder/src/test/org/apache/geronimo/jetty/deployment/StartupOrderComparatorTest.java Fri Jul  8 13:50:39 2005
@@ -0,0 +1,85 @@
+/**
+ *
+ * Copyright 2005 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.geronimo.jetty.deployment;
+
+import java.math.BigInteger;
+
+import junit.framework.TestCase;
+import org.apache.geronimo.xbeans.j2ee.ServletType;
+
+/**
+ * @version $Rev:  $ $Date:  $
+ */
+public class StartupOrderComparatorTest extends TestCase {
+
+    private final JettyModuleBuilder.StartupOrderComparator c = new JettyModuleBuilder.StartupOrderComparator();
+
+    public void testNoOrders() throws Exception {
+        ServletType s1 = makeServletType("a", -1);
+        ServletType s2 = makeServletType("b", -1);
+        ServletType s3 = makeServletType("c", -1);
+        checkOrdering(s1, s2, s3);
+    }
+
+    public void testIdenticalOrders() throws Exception {
+        ServletType s1 = makeServletType("a", 1);
+        ServletType s2 = makeServletType("b", 1);
+        ServletType s3 = makeServletType("c", 1);
+        checkOrdering(s1, s2, s3);
+    }
+
+    public void testDistinctOrders() throws Exception {
+        ServletType s1 = makeServletType("c", 1);
+        ServletType s2 = makeServletType("b", 2);
+        ServletType s3 = makeServletType("a", 3);
+        checkOrdering(s1, s2, s3);
+    }
+
+    public void testMixedOrders1() throws Exception {
+        ServletType s1 = makeServletType("c", 1);
+        ServletType s2 = makeServletType("b", 2);
+        ServletType s3 = makeServletType("a", -1);
+        checkOrdering(s1, s2, s3);
+    }
+
+    public void testMixedOrders2() throws Exception {
+        ServletType s1 = makeServletType("c", 1);
+        ServletType s2 = makeServletType("a", -1);
+        ServletType s3 = makeServletType("b", -1);
+        checkOrdering(s1, s2, s3);
+    }
+
+    private void checkOrdering(ServletType s1, ServletType s2, ServletType s3) {
+        //symmetric
+        assertTrue(c.compare(s1, s2) < 0);
+        assertTrue(c.compare(s2, s1) > 0);
+        //reflexive
+        assertTrue(c.compare(s1, s1) == 0);
+        //transitive
+        assertTrue(c.compare(s2, s3) < 0);
+        assertTrue(c.compare(s1, s3) < 0);
+    }
+
+    private ServletType makeServletType(String servletName, int order) {
+        ServletType s1 = ServletType.Factory.newInstance();
+        s1.addNewServletName().setStringValue(servletName);
+        if (order > -1) {
+            s1.addNewLoadOnStartup().setBigIntegerValue(BigInteger.valueOf(order));
+        }
+        return s1;
+    }
+}

Modified: geronimo/trunk/modules/jetty/src/java/org/apache/geronimo/jetty/JettyServletHolder.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/jetty/src/java/org/apache/geronimo/jetty/JettyServletHolder.java?rev=209887&r1=209886&r2=209887&view=diff
==============================================================================
--- geronimo/trunk/modules/jetty/src/java/org/apache/geronimo/jetty/JettyServletHolder.java (original)
+++ geronimo/trunk/modules/jetty/src/java/org/apache/geronimo/jetty/JettyServletHolder.java Fri Jul  8 13:50:39 2005
@@ -45,10 +45,11 @@
  */
 public class JettyServletHolder extends ServletHolder {
     private static final ThreadLocal currentServletName = new ThreadLocal();
+    private final JettyServletHolder previous;
 
     //todo consider interface instead of this constructor for endpoint use.
     public JettyServletHolder() {
-
+        this.previous = null;
     }
 
     public JettyServletHolder(String servletName,
@@ -58,10 +59,13 @@
                               Integer loadOnStartup,
                               Set servletMappings,
                               Map webRoleRefPermissions,
+                              JettyServletHolder previous,
                               JettyServletRegistration context) throws Exception {
         super(context == null? null: context.getServletHandler(), servletName, servletClassName, jspFile);
         //context will be null only for use as "default servlet info holder" in deployer.
 
+        this.previous = previous;
+
         if (context != null) {
             putAll(initParams);
             if (loadOnStartup != null) {
@@ -80,6 +84,10 @@
         return getName();
     }
 
+    public JettyServletHolder getPrevious() {
+        return previous;
+    }
+
     /**
      * Service a request with this servlet.  Set the ThreadLocal to hold the
      * current JettyServletHolder.
@@ -120,6 +128,8 @@
         infoBuilder.addAttribute("loadOnStartup", Integer.class, true);
         infoBuilder.addAttribute("servletMappings", Set.class, true);
         infoBuilder.addAttribute("webRoleRefPermissions", Map.class, true);
+
+        infoBuilder.addReference("Previous", JettyServletHolder.class, NameFactory.DEFAULT_SERVLET);
         infoBuilder.addReference("JettyServletRegistration", JettyServletRegistration.class, NameFactory.WEB_MODULE);
 
         infoBuilder.setConstructor(new String[] {"servletName",
@@ -129,6 +139,7 @@
                                                  "loadOnStartup",
                                                  "servletMappings",
                                                  "webRoleRefPermissions",
+                                                 "Previous",
                                                  "JettyServletRegistration"});
 
         GBEAN_INFO = infoBuilder.getBeanInfo();