Experimental support for Tomcat 5.0

git-svn-id: https://svn.apache.org/repos/asf/openejb/branches/tomcat50@634193 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/BackportUtil.java b/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/BackportUtil.java
index a197393..d8fc12b 100644
--- a/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/BackportUtil.java
+++ b/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/BackportUtil.java
@@ -16,31 +16,46 @@
  */
 package org.apache.openejb.tomcat.catalina;
 
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.List;
+import javax.servlet.Servlet;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.catalina.Service;
+import org.apache.catalina.Valve;
 import org.apache.catalina.Wrapper;
-import org.apache.catalina.deploy.NamingResources;
 import org.apache.catalina.core.NamingContextListener;
 import org.apache.catalina.core.StandardContext;
 import org.apache.catalina.core.StandardWrapper;
 import org.apache.catalina.deploy.ContextService;
+import org.apache.catalina.deploy.NamingResources;
+import org.apache.catalina.deploy.ResourceBase;
+import org.apache.naming.ContextAccessController;
+import org.apache.openejb.loader.SystemInstance;
+import org.apache.openejb.spi.SecurityService;
 import org.apache.openejb.tomcat.common.TomcatVersion;
-
-import javax.servlet.Servlet;
-import java.lang.reflect.Field;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
+import org.apache.openejb.util.OpenEjbVersion;
 
 /**
  * @version $Rev$ $Date$
  */
 public class BackportUtil {
 
-    private static API api;
+    private static final API api;
 
     static {
         if (TomcatVersion.v6.isTheVersion()){
             api = new Tomcat6();
-        } else {
+        } else if (TomcatVersion.v55.isTheVersion()){
             api = new Tomcat55();
+        } else {
+            api = new Tomcat50();
         }
     }
 
@@ -64,13 +79,124 @@
         getAPI().removeService(namingContextListener, serviceName);
     }
 
+    public static List<Connector> findConnectors(Service service) {
+        return getAPI().findConnectors(service);
+    }
+
+    public static ContextResourceEnvRef createResourceEnvRef(String name, String type) {
+        return getAPI().createResourceEnvRef(name, type);
+    }
+
+    public static ContextResourceEnvRef findResourceEnvRef(NamingResources namingResources, String name) {
+        return getAPI().findResourceEnvRef(namingResources, name);
+    }
+
+    public static List<ContextResourceEnvRef> findResourceEnvRefs(NamingResources namingResources) {
+        return getAPI().findResourceEnvRefs(namingResources);
+    }
+
+    public static void addResourceEnvRef(NamingResources naming, ContextResourceEnvRef ref) {
+        getAPI().addResourceEnvRef(naming, ref);
+    }
+
+    public static void replaceResourceEnvRefInListener(NamingContextListener namingContextListener, StandardContext standardContext, boolean addEntry, ContextResourceEnvRef ref) {
+        getAPI().replaceResourceEnvRefInListener(namingContextListener, standardContext, addEntry, ref);
+    }
+
+    public static Valve newOpenEJBValve() {
+        return getAPI().newOpenEJBValve();
+    }
+
+    public static void setRefProperty(Object ref, String refName, NamingResources naming, String propertyName, String propertyValue) {
+        getAPI().setRefProperty(ref, refName, naming, propertyName, propertyValue);
+    }
+
     public static interface API {
         Servlet getServlet(Wrapper wrapper);
         String findServiceName(NamingResources naming, String refName);
         NamingContextListener getNamingContextListener(StandardContext standardContext);
         void removeService(NamingContextListener namingContextListener, String serviceName);
+        List<Connector> findConnectors(Service service);
+        ContextResourceEnvRef findResourceEnvRef(NamingResources naming, String name);
+        List<ContextResourceEnvRef> findResourceEnvRefs(NamingResources naming);
+        void addResourceEnvRef(NamingResources naming, ContextResourceEnvRef ref);
+        void replaceResourceEnvRefInListener(NamingContextListener namingContextListener, StandardContext standardContext, boolean addEntry, ContextResourceEnvRef ref);
+        Valve newOpenEJBValve();
+        void setRefProperty(Object ref, String refName, NamingResources naming, String propertyName, String propertyValue);
+        ContextResourceEnvRef createResourceEnvRef(String name, String type);
     }
 
+    public static class Connector {
+        private final String scheme;
+        private final int port;
+
+        public Connector(String scheme, int port) {
+            this.scheme = scheme;
+            this.port = port;
+        }
+
+        public String getScheme() {
+            return scheme;
+        }
+
+        public int getPort() {
+            return port;
+        }
+    }
+
+    public interface ContextResourceEnvRef {
+        String getName();
+
+        String getType();
+
+        void setType(String type);
+    }
+
+    public static class Tomcat50ResourceEnvRef implements ContextResourceEnvRef {
+        private final String name;
+        private String type;
+
+        public Tomcat50ResourceEnvRef(String name, String type) {
+            this.name = name;
+            this.type = type;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public String getType() {
+            return type;
+        }
+
+        public void setType(String type) {
+            this.type = type;
+        }
+    }
+
+    public static class Tomcat6ResourceEnvRef implements ContextResourceEnvRef {
+        private final org.apache.catalina.deploy.ContextResourceEnvRef ref;
+
+        public Tomcat6ResourceEnvRef(org.apache.catalina.deploy.ContextResourceEnvRef ref) {
+            this.ref = ref;
+        }
+
+        public String getName() {
+            return ref.getName();
+        }
+
+        public String getType() {
+            return ref.getType();
+        }
+
+        public void setType(String s) {
+            ref.setType(s);
+        }
+
+        public void setProperty(String s, Object o) {
+            ref.setProperty(s, o);
+        }
+    }
 
     public static class Tomcat6 implements API {
         public Servlet getServlet(Wrapper wrapper) {
@@ -89,6 +215,61 @@
         public void removeService(NamingContextListener namingContextListener, String serviceName) {
             namingContextListener.removeService(serviceName);
         }
+
+        public List<Connector> findConnectors(Service service) {
+            List<Connector> connectors = new ArrayList<Connector>();
+            for (org.apache.catalina.connector.Connector connector : service.findConnectors()) {
+                connectors.add(new Connector(connector.getScheme(), connector.getPort()));
+            }
+            return connectors;
+        }
+
+        public ContextResourceEnvRef createResourceEnvRef(String name, String type) {
+            org.apache.catalina.deploy.ContextResourceEnvRef ref = new org.apache.catalina.deploy.ContextResourceEnvRef();
+            ref.setName(name);
+            ref.setType(type);
+            return new Tomcat6ResourceEnvRef(ref);
+        }
+
+        public ContextResourceEnvRef findResourceEnvRef(NamingResources namingResources, String name) {
+            org.apache.catalina.deploy.ContextResourceEnvRef ref = namingResources.findResourceEnvRef(name);
+            if (ref == null) return null;
+            return new Tomcat6ResourceEnvRef(ref);
+        }
+
+        public List<ContextResourceEnvRef> findResourceEnvRefs(NamingResources namingResources) {
+            List<ContextResourceEnvRef> resourceEnvRefs = new ArrayList<ContextResourceEnvRef>();
+            for (org.apache.catalina.deploy.ContextResourceEnvRef ref : namingResources.findResourceEnvRefs()) {
+                resourceEnvRefs.add(new Tomcat6ResourceEnvRef(ref));
+            }
+            return resourceEnvRefs;
+        }
+
+        public void addResourceEnvRef(NamingResources naming, ContextResourceEnvRef ref) {
+            naming.addResourceEnvRef(((Tomcat6ResourceEnvRef) ref).ref);
+        }
+
+        public void replaceResourceEnvRefInListener(NamingContextListener namingContextListener, StandardContext standardContext, boolean addEntry, ContextResourceEnvRef ref) {
+            ContextAccessController.setWritable(namingContextListener.getName(), standardContext);
+            if (!addEntry) namingContextListener.removeResourceEnvRef(ref.getName());
+            namingContextListener.addResourceEnvRef(((Tomcat6ResourceEnvRef) ref).ref);
+            ContextAccessController.setReadOnly(namingContextListener.getName());
+        }
+
+        public Valve newOpenEJBValve() {
+            return new OpenEJBValve();
+        }
+
+        public void setRefProperty(Object ref, String refName, NamingResources naming, String propertyName, String propertyValue) {
+            if (ref instanceof ResourceBase) {
+                ResourceBase resourceBase = (ResourceBase) ref;
+                resourceBase.setProperty(propertyName, propertyValue);
+            }
+            if (ref instanceof Tomcat6ResourceEnvRef) {
+                Tomcat6ResourceEnvRef contextResourceEnvRef = (Tomcat6ResourceEnvRef) ref;
+                contextResourceEnvRef.ref.setProperty(propertyName, propertyValue);
+            }
+        }
     }
 
     public static class Tomcat55 implements API {
@@ -124,6 +305,62 @@
         public void removeService(NamingContextListener namingContextListener, String serviceName) {
         }
 
+
+        public List<Connector> findConnectors(Service service) {
+            List<Connector> connectors = new ArrayList<Connector>();
+            for (org.apache.catalina.connector.Connector connector : service.findConnectors()) {
+                connectors.add(new Connector(connector.getScheme(), connector.getPort()));
+            }
+            return connectors;
+        }
+
+        public ContextResourceEnvRef createResourceEnvRef(String name, String type) {
+            org.apache.catalina.deploy.ContextResourceEnvRef ref = new org.apache.catalina.deploy.ContextResourceEnvRef();
+            ref.setName(name);
+            ref.setType(type);
+            return new Tomcat6ResourceEnvRef(ref);
+        }
+
+        public ContextResourceEnvRef findResourceEnvRef(NamingResources namingResources, String name) {
+            org.apache.catalina.deploy.ContextResourceEnvRef ref = namingResources.findResourceEnvRef(name);
+            if (ref == null) return null;
+            return new Tomcat6ResourceEnvRef(ref);
+        }
+
+        public List<ContextResourceEnvRef> findResourceEnvRefs(NamingResources namingResources) {
+            List<ContextResourceEnvRef> resourceEnvRefs = new ArrayList<ContextResourceEnvRef>();
+            for (org.apache.catalina.deploy.ContextResourceEnvRef ref : namingResources.findResourceEnvRefs()) {
+                resourceEnvRefs.add(new Tomcat6ResourceEnvRef(ref));
+            }
+            return resourceEnvRefs;
+        }
+
+        public void addResourceEnvRef(NamingResources naming, ContextResourceEnvRef ref) {
+            naming.addResourceEnvRef(((Tomcat6ResourceEnvRef) ref).ref);
+        }
+
+        public void replaceResourceEnvRefInListener(NamingContextListener namingContextListener, StandardContext standardContext, boolean addEntry, ContextResourceEnvRef ref) {
+            ContextAccessController.setWritable(namingContextListener.getName(), standardContext);
+            if (!addEntry) namingContextListener.removeResourceEnvRef(ref.getName());
+            namingContextListener.addResourceEnvRef(((Tomcat6ResourceEnvRef) ref).ref);
+            ContextAccessController.setReadOnly(namingContextListener.getName());
+        }
+
+        public Valve newOpenEJBValve() {
+            return new OpenEJBValve();
+        }
+
+        public void setRefProperty(Object ref, String refName, NamingResources naming, String propertyName, String propertyValue) {
+            if (ref instanceof ResourceBase) {
+                ResourceBase resourceBase = (ResourceBase) ref;
+                resourceBase.setProperty(propertyName, propertyValue);
+            }
+            if (ref instanceof Tomcat6ResourceEnvRef) {
+                Tomcat6ResourceEnvRef contextResourceEnvRef = (Tomcat6ResourceEnvRef) ref;
+                contextResourceEnvRef.ref.setProperty(propertyName, propertyValue);
+            }
+        }
+
         private Field getField(final Class clazz, final String name) {
             return AccessController.doPrivileged(new PrivilegedAction<Field>() {
                 public Field run() {
@@ -137,9 +374,199 @@
                 }
             });
         }
-
     }
 
+    public static class Tomcat50 extends Tomcat55 {
+        private final Method findConnectors;
+        private final Method getScheme;
+        private final Method findResourceEnvRef;
+        private final Method findResourceEnvRefs;
+        private final Method addResourceEnvRef;
+        private final Method findResourceParams;
+        private final Method addResourceParams;
 
+        private final Method listenerAddResourceEnvRef;
+        private final Method listenerRemoveResourceEnvRef;
+
+        protected Class<?> resourceParamsClass;
+        private final Method setResourceParamsName;
+        private final Method addParameter;
+
+        public Tomcat50() {
+            try {
+                findConnectors = Service.class.getMethod("findConnectors");
+                Class<?> connectorClass = Service.class.getClassLoader().loadClass("org.apache.catalina.Connector");
+                getScheme = connectorClass.getMethod("getScheme");
+
+                resourceParamsClass = Service.class.getClassLoader().loadClass("org.apache.catalina.deploy.ResourceParams");
+                addParameter = resourceParamsClass.getMethod("addParameter", String.class, String.class);
+                setResourceParamsName = resourceParamsClass.getMethod("setName", String.class);
+
+                findResourceEnvRef = NamingResources.class.getMethod("findResourceEnvRef", String.class);
+                findResourceEnvRefs = NamingResources.class.getMethod("findResourceEnvRefs");
+                addResourceEnvRef = NamingResources.class.getMethod("addResourceEnvRef", String.class, String.class);
+                findResourceParams = NamingResources.class.getMethod("findResourceParams", String.class);
+                addResourceParams = NamingResources.class.getMethod("addResourceParams", resourceParamsClass);
+
+                listenerAddResourceEnvRef = NamingContextListener.class.getMethod("addResourceEnvRef", String.class, String.class);
+                listenerRemoveResourceEnvRef = NamingContextListener.class.getMethod("removeResourceEnvRef", String.class);
+            } catch (Exception e) {
+                throw (IllegalStateException) new IllegalStateException("Unable to initialize Tomcat 5.0 API translation layer").initCause(e);
+            }
+        }
+
+        public List<Connector> findConnectors(Service service) {
+            try {
+                List<Connector> connectors = new ArrayList<Connector>();
+                for (Object connector : (Object[])findConnectors.invoke(service)) {
+                    int port;
+                    try {
+                        // getPort is not a method on the connector interface but the implementation classes
+                        Method getPort = connector.getClass().getMethod("getPort");
+                        port = (Integer) getPort.invoke(connector);
+                    } catch (NoSuchMethodException e) {
+                        // ignore wacky connector without a port
+                        continue;
+                    }
+
+                    String scheme = (String) getScheme.invoke(connector);
+
+                    connectors.add(new Connector(scheme, port));
+                }
+                return connectors;
+            } catch (Exception e) {
+                throw (IllegalStateException) new IllegalStateException("Error finding Tomcat 5.0 connectors").initCause(e);
+            }
+        }
+
+        public ContextResourceEnvRef createResourceEnvRef(String name, String type) {
+            return new Tomcat50ResourceEnvRef(name, type);
+        }
+
+        public ContextResourceEnvRef findResourceEnvRef(NamingResources namingResources, String name) {
+            try {
+                String type = (String) findResourceEnvRef.invoke(namingResources, name);
+                if (type == null) return null;
+                return new Tomcat50ResourceEnvRef(name, type);
+            } catch (Exception e) {
+                throw (IllegalStateException) new IllegalStateException("Error finding Tomcat 5.0 resource env refs").initCause(e);
+            }
+        }
+
+        public List<ContextResourceEnvRef> findResourceEnvRefs(NamingResources namingResources) {
+            try {
+                List<ContextResourceEnvRef> resourceEnvRefs = new ArrayList<ContextResourceEnvRef>();
+                for (String name : (String[])findResourceEnvRefs.invoke(namingResources)) {
+                    String type = (String) findResourceEnvRef.invoke(namingResources, name);
+                    resourceEnvRefs.add(new Tomcat50ResourceEnvRef(name, type));
+                }
+                return resourceEnvRefs;
+            } catch (Exception e) {
+                throw (IllegalStateException) new IllegalStateException("Error finding Tomcat 5.0 resource env refs").initCause(e);
+            }
+        }
+
+        public void addResourceEnvRef(NamingResources naming, ContextResourceEnvRef ref) {
+            try {
+                addResourceEnvRef.invoke(naming, ref.getName(), ref.getType());
+            } catch (Exception e) {
+                throw (IllegalStateException) new IllegalStateException("Error finding Tomcat 5.0 resource env refs").initCause(e);
+            }
+        }
+
+        public void replaceResourceEnvRefInListener(NamingContextListener namingContextListener, StandardContext standardContext, boolean addEntry, ContextResourceEnvRef ref) {
+            try {
+                ContextAccessController.setWritable(namingContextListener.getName(), standardContext);
+                if (!addEntry) {
+                    listenerRemoveResourceEnvRef.invoke(namingContextListener, ref.getName());
+                }
+                listenerAddResourceEnvRef.invoke(namingContextListener, ref.getName(), ref.getType());
+                ContextAccessController.setReadOnly(namingContextListener.getName());
+            } catch (Exception e) {
+                throw (IllegalStateException) new IllegalStateException("Error finding Tomcat 5.0 resource env refs").initCause(e);
+            }
+        }
+
+        public void setRefProperty(Object ref, String refName, NamingResources naming, String propertyName, String propertyValue) {
+            try {
+                Object resourceParams = findResourceParams.invoke(naming, refName);
+                if (resourceParams == null) {
+                    resourceParams = resourceParamsClass.newInstance();
+                    setResourceParamsName.invoke(resourceParams, refName);
+                    addResourceParams.invoke(naming, resourceParams);
+                }
+                addParameter.invoke(resourceParams, propertyName, propertyValue);
+            } catch (Exception e) {
+                throw (IllegalStateException) new IllegalStateException("Error finding Tomcat 5.0 resource env refs").initCause(e);
+            }
+        }
+
+        public Valve newOpenEJBValve() {
+            Valve valve = (Valve) Proxy.newProxyInstance(getClass().getClassLoader(), new Class[] {Valve.class}, new ValveInvocationHandler());
+            return valve;
+        }
+
+        private static class ValveInvocationHandler implements InvocationHandler {
+            private static final Method getInfo;
+            private static final Method invoke;
+            private static final Method invokeNext;
+            private static final Method getWrapper;
+            private static final Method getRequest;
+
+            static {
+                try {
+                    getInfo = Valve.class.getMethod("getInfo");
+
+                    ClassLoader classLoader = Valve.class.getClassLoader();
+                    Class<?> requestClass = classLoader.loadClass("org.apache.catalina.Request");
+                    Class<?> responseClass = classLoader.loadClass("org.apache.catalina.Response");
+                    Class<?> valveContext = classLoader.loadClass("org.apache.catalina.ValveContext");
+                    invoke = Valve.class.getMethod("invoke", requestClass, responseClass, valveContext);
+
+                    invokeNext = valveContext.getMethod("invokeNext", requestClass, responseClass);
+                    getWrapper = requestClass.getMethod("getWrapper");
+                    getRequest = requestClass.getMethod("getRequest");
+                } catch (Exception e) {
+                    throw (IllegalStateException) new IllegalStateException("Unable to initialize Tomcat 5.0 API translation layer").initCause(e);
+                }
+            }
+
+            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+                if (getInfo.equals(method)) {
+                    return "OpenEJBValve/" + OpenEjbVersion.get().getVersion();
+                } else if (invoke.equals(method)) {
+                    Object request = args[0];
+                    Object response = args[1];
+                    Object valveContext = args[2];
+
+                    Object oldState = null;
+
+                    TomcatSecurityService securityService = getSecurityService();
+                    Wrapper wrapper = (Wrapper) getWrapper.invoke(request);
+                    if (securityService != null && wrapper != null) {
+                        HttpServletRequest servletRequest = (HttpServletRequest) getRequest.invoke(request);
+                        oldState = securityService.enterWebApp(wrapper.getRealm(), servletRequest.getUserPrincipal(), wrapper.getRunAs());
+                    }
+
+                    try {
+                        invokeNext.invoke(valveContext, request, response);
+                    } finally {
+                        if (securityService != null) {
+                            securityService.exitWebApp(oldState);
+                        }
+                    }
+                }
+                return null;
+            }
+
+            private TomcatSecurityService getSecurityService() {
+                SecurityService securityService =  SystemInstance.get().getComponent(SecurityService.class);
+                if (securityService instanceof TomcatSecurityService) {
+                    return (TomcatSecurityService) securityService;
+                }
+                return null;
+            }
+        }
+    }
 
 }
diff --git a/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/ContextListener.java b/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/ContextListener.java
index af2d3f0..a8f98aa 100644
--- a/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/ContextListener.java
+++ b/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/ContextListener.java
@@ -22,14 +22,12 @@
 import org.apache.catalina.core.StandardHost;
 
 public interface ContextListener {
-    void init(StandardContext context);
     void beforeStart(StandardContext context);
     void start(StandardContext context);
     void afterStart(StandardContext context);
     void beforeStop(StandardContext context);
     void stop(StandardContext context);
     void afterStop(StandardContext context);
-    void destroy(StandardContext context);
 
     void afterStop(StandardServer standardServer);
 
diff --git a/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/GlobalListenerSupport.java b/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/GlobalListenerSupport.java
index 83049b8..a728245 100644
--- a/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/GlobalListenerSupport.java
+++ b/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/GlobalListenerSupport.java
@@ -22,11 +22,14 @@
 import org.apache.catalina.LifecycleListener;
 import org.apache.catalina.Service;
 import org.apache.catalina.Lifecycle;
+import org.apache.catalina.ContainerListener;
+import org.apache.catalina.ContainerEvent;
 import org.apache.catalina.core.ContainerBase;
 import org.apache.catalina.core.StandardContext;
 import org.apache.catalina.core.StandardEngine;
 import org.apache.catalina.core.StandardHost;
 import org.apache.catalina.core.StandardServer;
+import org.apache.openejb.tomcat.common.TomcatVersion;
 
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
@@ -34,7 +37,7 @@
 import java.util.HashMap;
 import java.util.Map;
 
-public class GlobalListenerSupport implements PropertyChangeListener, LifecycleListener {
+public class GlobalListenerSupport implements PropertyChangeListener, LifecycleListener, ContainerListener {
     private final StandardServer standardServer;
     private final ContextListener contextListener;
 
@@ -50,9 +53,7 @@
         if (source instanceof StandardContext) {
             StandardContext standardContext = (StandardContext) source;
             String type = event.getType();
-            if (Lifecycle.INIT_EVENT.equals(type)) {
-                contextListener.init(standardContext);
-            } else if (Lifecycle.BEFORE_START_EVENT.equals(type)) {
+            if (Lifecycle.BEFORE_START_EVENT.equals(type)) {
                 contextListener.beforeStart(standardContext);
             } else if (Lifecycle.START_EVENT.equals(type)) {
                 contextListener.start(standardContext);
@@ -64,13 +65,11 @@
                 contextListener.stop(standardContext);
             } else if (Lifecycle.AFTER_STOP_EVENT.equals(type)) {
                 contextListener.afterStop(standardContext);
-            } else if (Lifecycle.DESTROY_EVENT.equals(type)) {
-                contextListener.destroy(standardContext);
             }
         } else if (source instanceof StandardHost) {
             StandardHost standardHost = (StandardHost) source;
             String type = event.getType();
-            if (Lifecycle.PERIODIC_EVENT.equals(type)) {
+            if ("periodic".equals(type)) {
                 contextListener.checkHost(standardHost);
             }
         } else if (source instanceof StandardServer) {
@@ -82,6 +81,17 @@
         }
     }
 
+    public void containerEvent(ContainerEvent event) {
+        Object source = event.getSource();
+        if (source instanceof StandardHost) {
+            String type = event.getType();
+            if ("pre-install".equals(type)) {
+                Object newValue = event.getData();
+                contextAdded((StandardContext) newValue);
+            }
+        }
+    }
+
     public void start() {
         // hook the hosts so we get notified before contexts are started
         standardServer.addPropertyChangeListener(this);
@@ -131,7 +141,14 @@
     }
 
     private void hostAdded(StandardHost host) {
-        addContextListener(host);
+        if (TomcatVersion.v50.isTheVersion()) {
+            // Tomcat5 fires events throught the container listener interface
+            host.addContainerListener(this);
+        } else {
+            // Tomcat6 doen't actually fire a before start event, so we need to
+            // hook the map
+            addContextListener(host);
+        }
         host.addLifecycleListener(this);
         for (Container child : host.findChildren()) {
             if (child instanceof StandardContext) {
diff --git a/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/OpenEJBNamingContextListener.java b/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/OpenEJBNamingContextListener.java
index 25c362b..311ddd9 100644
--- a/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/OpenEJBNamingContextListener.java
+++ b/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/OpenEJBNamingContextListener.java
@@ -25,7 +25,6 @@
 import org.apache.catalina.deploy.ContextEnvironment;
 import org.apache.catalina.deploy.ContextLocalEjb;
 import org.apache.catalina.deploy.ContextResource;
-import org.apache.catalina.deploy.ContextResourceEnvRef;
 import org.apache.catalina.deploy.ContextResourceLink;
 import org.apache.catalina.deploy.NamingResources;
 import org.apache.openejb.OpenEJBException;
@@ -33,6 +32,7 @@
 import org.apache.openejb.assembler.classic.ResourceInfo;
 import org.apache.openejb.assembler.dynamic.PassthroughFactory;
 import org.apache.openejb.loader.SystemInstance;
+import org.apache.openejb.tomcat.catalina.BackportUtil.ContextResourceEnvRef;
 import org.apache.openejb.util.LogCategory;
 import org.apache.openejb.util.Logger;
 
@@ -40,6 +40,7 @@
 import javax.naming.NamingException;
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
+import java.util.List;
 
 @SuppressWarnings({"UnusedDeclaration"})
 public class OpenEJBNamingContextListener implements LifecycleListener, PropertyChangeListener {
@@ -219,7 +220,7 @@
         }
 
         // Resources Env
-        ContextResourceEnvRef[] resourceEnvRefs = namingResources.findResourceEnvRefs();
+        List<ContextResourceEnvRef> resourceEnvRefs = BackportUtil.findResourceEnvRefs(namingResources);
         for (ContextResourceEnvRef resourceEnvRef : resourceEnvRefs) {
             addResourceEnvRef(resourceEnvRef);
         }
diff --git a/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/OpenEJBValve.java b/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/OpenEJBValve.java
index 8132644..1417c3f 100644
--- a/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/OpenEJBValve.java
+++ b/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/OpenEJBValve.java
@@ -20,6 +20,7 @@
 import org.apache.catalina.connector.Request;
 import org.apache.catalina.connector.Response;
 import org.apache.catalina.valves.ValveBase;
+import org.apache.catalina.Wrapper;
 import org.apache.openejb.loader.SystemInstance;
 import org.apache.openejb.spi.SecurityService;
 import org.apache.openejb.util.OpenEjbVersion;
@@ -37,8 +38,10 @@
 
     public void invoke(Request request, Response response) throws IOException, ServletException {
         Object oldState = null;
-        if (securityService != null && request.getWrapper() != null) {
-            oldState = securityService.enterWebApp(request.getWrapper().getRealm(), request.getUserPrincipal(), request.getWrapper().getRunAs());
+
+        Wrapper wrapper = request.getWrapper();
+        if (securityService != null && wrapper != null) {
+            oldState = securityService.enterWebApp(wrapper.getRealm(), request.getUserPrincipal(), wrapper.getRunAs());
         }
 
         try {
diff --git a/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/TomcatJndiBuilder.java b/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/TomcatJndiBuilder.java
index 25f59ff..bfeed91 100644
--- a/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/TomcatJndiBuilder.java
+++ b/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/TomcatJndiBuilder.java
@@ -22,7 +22,6 @@
 import org.apache.catalina.deploy.ContextEjb;
 import org.apache.catalina.deploy.ContextEnvironment;
 import org.apache.catalina.deploy.ContextResource;
-import org.apache.catalina.deploy.ContextResourceEnvRef;
 import org.apache.catalina.deploy.ContextTransaction;
 import org.apache.catalina.deploy.NamingResources;
 import org.apache.naming.ContextAccessController;
@@ -46,6 +45,7 @@
 import org.apache.openejb.loader.SystemInstance;
 import org.apache.openejb.persistence.JtaEntityManager;
 import org.apache.openejb.persistence.JtaEntityManagerRegistry;
+import org.apache.openejb.tomcat.catalina.BackportUtil.ContextResourceEnvRef;
 import static org.apache.openejb.tomcat.common.NamingUtil.DEPLOYMENT_ID;
 import static org.apache.openejb.tomcat.common.NamingUtil.EXTENDED;
 import static org.apache.openejb.tomcat.common.NamingUtil.EXTERNAL;
@@ -68,6 +68,8 @@
 import org.apache.openejb.tomcat.common.PersistenceContextFactory;
 import org.apache.openejb.tomcat.common.UserTransactionFactory;
 import org.apache.openejb.tomcat.common.NamingUtil;
+import org.apache.openejb.tomcat.common.TomcatVersion;
+import static org.apache.openejb.tomcat.catalina.BackportUtil.setRefProperty;
 
 import javax.persistence.EntityManager;
 import javax.persistence.EntityManagerFactory;
@@ -142,9 +144,11 @@
         for (ServiceReferenceInfo ref : webAppInfo.jndiEnc.serviceRefs) {
             mergeRef(naming, ref);
         }
-        ContextTransaction contextTransaction = new ContextTransaction();
-        contextTransaction.setProperty(Constants.FACTORY, UserTransactionFactory.class.getName());
-        naming.setTransaction(contextTransaction);
+        if (TomcatVersion.v6.isTheVersion() || TomcatVersion.v55.isTheVersion()) {
+            ContextTransaction contextTransaction = new ContextTransaction();
+            contextTransaction.setProperty(Constants.FACTORY, UserTransactionFactory.class.getName());
+            naming.setTransaction(contextTransaction);
+        }
     }
 
     public void mergeRef(NamingResources naming, EnvEntryInfo ref) {
@@ -180,23 +184,23 @@
             addEntry = true;
         }
 
-        ejb.setProperty(Constants.FACTORY, EjbFactory.class.getName());
-        ejb.setProperty(NAME, ref.referenceName);
+        setRefProperty(ejb, ref.referenceName, naming, Constants.FACTORY, EjbFactory.class.getName());
+        setRefProperty(ejb, ref.referenceName, naming, NAME, ref.referenceName);
         ejb.setHome(ref.homeType);
         ejb.setRemote(ref.interfaceType);
         ejb.setLink(null);
         ejb.setType(ref.interfaceType);
         if (useCrossClassLoaderRef) {
-            ejb.setProperty(EXTERNAL, "" + ref.externalReference);
+            setRefProperty(ejb, ref.referenceName, naming, EXTERNAL, "" + ref.externalReference);
         }
 
         if (ref.ejbDeploymentId != null) {
-            ejb.setProperty(DEPLOYMENT_ID, ref.ejbDeploymentId);
+            setRefProperty(ejb, ref.referenceName, naming, DEPLOYMENT_ID, ref.ejbDeploymentId);
         }
 
         if (ref.location != null) {
-            ejb.setProperty(JNDI_NAME, ref.location.jndiName);
-            ejb.setProperty(JNDI_PROVIDER_ID, ref.location.jndiProviderId);
+            setRefProperty(ejb, ref.referenceName, naming, JNDI_NAME, ref.location.jndiName);
+            setRefProperty(ejb, ref.referenceName, naming, JNDI_PROVIDER_ID, ref.location.jndiProviderId);
         }
 
         if (addEntry) {
@@ -221,21 +225,21 @@
             addEntry = true;
         }
 
-        ejb.setProperty(Constants.FACTORY, EjbFactory.class.getName());
-        ejb.setProperty(NAME, ref.referenceName);
+        setRefProperty(ejb, ref.referenceName, naming, Constants.FACTORY, EjbFactory.class.getName());
+        setRefProperty(ejb, ref.referenceName, naming, NAME, ref.referenceName);
         ejb.setHome(ref.homeType);
         ejb.setRemote(null);
-        ejb.setProperty(LOCAL, ref.interfaceType);
+        setRefProperty(ejb, ref.referenceName, naming, LOCAL, ref.interfaceType);
         ejb.setLink(null);
         ejb.setType(ref.interfaceType);
 
         if (ref.ejbDeploymentId != null) {
-            ejb.setProperty(DEPLOYMENT_ID, ref.ejbDeploymentId);
+            setRefProperty(ejb, ref.referenceName, naming, DEPLOYMENT_ID, ref.ejbDeploymentId);
         }
 
         if (ref.location != null) {
-            ejb.setProperty(JNDI_NAME, ref.location.jndiName);
-            ejb.setProperty(JNDI_PROVIDER_ID, ref.location.jndiProviderId);
+            setRefProperty(ejb, ref.referenceName, naming, JNDI_NAME, ref.location.jndiName);
+            setRefProperty(ejb, ref.referenceName, naming, JNDI_PROVIDER_ID, ref.location.jndiProviderId);
         }
 
         if (addEntry) {
@@ -260,21 +264,21 @@
             addEntry = true;
         }
 
-        resource.setProperty(Constants.FACTORY, PersistenceContextFactory.class.getName());
-        resource.setProperty(NAME, ref.referenceName);
+        setRefProperty(resource, ref.referenceName, naming, Constants.FACTORY, PersistenceContextFactory.class.getName());
+        setRefProperty(resource, ref.referenceName, naming, NAME, ref.referenceName);
         resource.setType(EntityManager.class.getName());
 
         if (ref.persistenceUnitName != null) {
-            resource.setProperty(UNIT, ref.persistenceUnitName);
+            setRefProperty(resource, ref.referenceName, naming, UNIT, ref.persistenceUnitName);
         }
-        resource.setProperty(EXTENDED, "" + ref.extended);
+        setRefProperty(resource, ref.referenceName, naming, EXTENDED, "" + ref.extended);
         if (ref.properties != null) {
             // resource.setProperty(NamingConstants.PROPERTIES, ref.properties);
         }
 
         if (ref.location != null) {
-            resource.setProperty(JNDI_NAME, ref.location.jndiName);
-            resource.setProperty(JNDI_PROVIDER_ID, ref.location.jndiProviderId);
+            setRefProperty(resource, ref.referenceName, naming, JNDI_NAME, ref.location.jndiName);
+            setRefProperty(resource, ref.referenceName, naming, JNDI_PROVIDER_ID, ref.location.jndiProviderId);
         } else {
             Context context = SystemInstance.get().getComponent(ContainerSystem.class).getJNDIContext();
             EntityManagerFactory factory;
@@ -287,7 +291,7 @@
             JtaEntityManagerRegistry jtaEntityManagerRegistry = SystemInstance.get().getComponent(JtaEntityManagerRegistry.class);
             JtaEntityManager jtaEntityManager = new JtaEntityManager(jtaEntityManagerRegistry, factory, ref.properties, ref.extended);
             Object object = jtaEntityManager;
-            setResource(resource, object);
+            setResource(naming, resource, object);
         }
 
         if (addEntry) {
@@ -312,17 +316,17 @@
             addEntry = true;
         }
 
-        resource.setProperty(Constants.FACTORY, PersistenceUnitFactory.class.getName());
-        resource.setProperty(NAME, ref.referenceName);
+        setRefProperty(resource, ref.referenceName, naming, Constants.FACTORY, PersistenceUnitFactory.class.getName());
+        setRefProperty(resource, ref.referenceName, naming, NAME, ref.referenceName);
         resource.setType(EntityManagerFactory.class.getName());
 
         if (ref.persistenceUnitName != null) {
-            resource.setProperty(UNIT, ref.persistenceUnitName);
+            setRefProperty(resource, ref.referenceName, naming, UNIT, ref.persistenceUnitName);
         }
 
         if (ref.location != null) {
-            resource.setProperty(JNDI_NAME, ref.location.jndiName);
-            resource.setProperty(JNDI_PROVIDER_ID, ref.location.jndiProviderId);
+            setRefProperty(resource, ref.referenceName, naming, JNDI_NAME, ref.location.jndiName);
+            setRefProperty(resource, ref.referenceName, naming, JNDI_PROVIDER_ID, ref.location.jndiProviderId);
         } else {
             // TODO: This will not work if webapps don't use AutoConfi
             Context context = SystemInstance.get().getComponent(ContainerSystem.class).getJNDIContext();
@@ -332,7 +336,7 @@
             } catch (NamingException e) {
                 throw new IllegalStateException("PersistenceUnit '" + ref.unitId + "' not found for EXTENDED ref '" + ref.referenceName + "'");
             }
-            setResource(resource, factory);
+            setResource(naming, resource, factory);
         }
 
         if (addEntry) {
@@ -356,13 +360,13 @@
             addEntry = true;
         }
 
-        resource.setProperty(Constants.FACTORY, ResourceFactory.class.getName());
-        resource.setProperty(NAME, ref.referenceName);
+        setRefProperty(resource, ref.referenceName, naming, Constants.FACTORY, ResourceFactory.class.getName());
+        setRefProperty(resource, ref.referenceName, naming, NAME, ref.referenceName);
         resource.setType(ref.referenceType);
         resource.setAuth(ref.referenceAuth);
 
         if (ref.resourceID != null) {
-            resource.setProperty(RESOURCE_ID, ref.resourceID);
+            setRefProperty(resource, ref.referenceName, naming, RESOURCE_ID, ref.resourceID);
         }
 
         if (ref.properties != null) {
@@ -370,8 +374,8 @@
         }
 
         if (ref.location != null) {
-            resource.setProperty(JNDI_NAME, ref.location.jndiName);
-            resource.setProperty(JNDI_PROVIDER_ID, ref.location.jndiProviderId);
+            setRefProperty(resource, ref.referenceName, naming, JNDI_NAME, ref.location.jndiName);
+            setRefProperty(resource, ref.referenceName, naming, JNDI_PROVIDER_ID, ref.location.jndiProviderId);
         }
 
         if (addEntry) {
@@ -387,40 +391,35 @@
     }
 
     public void mergeRef(NamingResources naming, ResourceEnvReferenceInfo ref) {
-        ContextResourceEnvRef resourceEnv = naming.findResourceEnvRef(ref.resourceEnvRefName);
+        ContextResourceEnvRef resourceEnv = BackportUtil.findResourceEnvRef(naming,  ref.resourceEnvRefName);
         boolean addEntry = false;
         if (resourceEnv == null) {
-            resourceEnv = new ContextResourceEnvRef();
-            resourceEnv.setName(ref.resourceEnvRefName);
-            addEntry = true;
+            resourceEnv = BackportUtil.createResourceEnvRef(ref.resourceEnvRefName, ref.resourceEnvRefType);
         }
 
         if (UserTransaction.class.getName().equals(ref.resourceEnvRefType)) {
-            resourceEnv.setProperty(Constants.FACTORY, UserTransactionFactory.class.getName());
+            setRefProperty(resourceEnv, ref.resourceEnvRefName, naming, Constants.FACTORY, UserTransactionFactory.class.getName());
         } else {
-            resourceEnv.setProperty(Constants.FACTORY, ResourceFactory.class.getName());
-            resourceEnv.setProperty(NAME, ref.resourceEnvRefName);
+            setRefProperty(resourceEnv, ref.resourceEnvRefName, naming, Constants.FACTORY, ResourceFactory.class.getName());
+            setRefProperty(resourceEnv, ref.resourceEnvRefName, naming, NAME, ref.resourceEnvRefName);
             resourceEnv.setType(ref.resourceEnvRefType);
 
             if (ref.resourceID != null) {
-                resourceEnv.setProperty(RESOURCE_ID, ref.resourceID);
+                setRefProperty(resourceEnv, ref.resourceEnvRefName, naming, RESOURCE_ID, ref.resourceID);
             }
 
             if (ref.location != null) {
-                resourceEnv.setProperty(JNDI_NAME, ref.location.jndiName);
-                resourceEnv.setProperty(JNDI_PROVIDER_ID, ref.location.jndiProviderId);
+                setRefProperty(resourceEnv, ref.resourceEnvRefName, naming, JNDI_NAME, ref.location.jndiName);
+                setRefProperty(resourceEnv, ref.resourceEnvRefName, naming, JNDI_PROVIDER_ID, ref.location.jndiProviderId);
             }
         }
 
         if (addEntry) {
-            naming.addResourceEnvRef(resourceEnv);
+            BackportUtil.addResourceEnvRef(naming, resourceEnv);
         }
 
         if (replaceEntry) {
-            ContextAccessController.setWritable(namingContextListener.getName(), standardContext);
-            if (!addEntry) namingContextListener.removeResourceEnvRef(resourceEnv.getName());
-            namingContextListener.addResourceEnvRef(resourceEnv);
-            ContextAccessController.setReadOnly(namingContextListener.getName());
+            BackportUtil.replaceResourceEnvRefInListener(namingContextListener, standardContext, addEntry, resourceEnv);
         }
     }
 
@@ -433,8 +432,8 @@
             addEntry = true;
         }
 
-        resource.setProperty(Constants.FACTORY, WsFactory.class.getName());
-        resource.setProperty(NAME, ref.referenceName);
+        setRefProperty(resource, ref.referenceName, naming, Constants.FACTORY, WsFactory.class.getName());
+        setRefProperty(resource, ref.referenceName, naming, NAME, ref.referenceName);
         if (ref.referenceType != null) {
             resource.setType(ref.referenceType);
         } else {
@@ -442,29 +441,29 @@
         }
 
         if (ref.location != null) {
-            resource.setProperty(JNDI_NAME, ref.location.jndiName);
-            resource.setProperty(JNDI_PROVIDER_ID, ref.location.jndiProviderId);
+            setRefProperty(resource, ref.referenceName, naming, JNDI_NAME, ref.location.jndiName);
+            setRefProperty(resource, ref.referenceName, naming, JNDI_PROVIDER_ID, ref.location.jndiProviderId);
         } else {
             // ID
             if (ref.id != null) {
-                resource.setProperty(WS_ID, ref.id);
+                setRefProperty(resource, ref.referenceName, naming, WS_ID, ref.id);
             }
             // Service QName
             if (ref.serviceQName != null) {
-                resource.setProperty(WS_QNAME, ref.serviceQName.toString());
+                setRefProperty(resource, ref.referenceName, naming, WS_QNAME, ref.serviceQName.toString());
             }
             // Service Class
-            resource.setProperty(WS_CLASS, ref.serviceType);
+            setRefProperty(resource, ref.referenceName, naming, WS_CLASS, ref.serviceType);
 
             // Port QName
             if (ref.portQName != null) {
-                resource.setProperty(WS_PORT_QNAME, ref.portQName.toString());
+                setRefProperty(resource, ref.referenceName, naming, WS_PORT_QNAME, ref.portQName.toString());
             }
 
             // add the wsdl url
             URL wsdlURL = getWsdlUrl(ref);
             if (wsdlURL != null) {
-                resource.setProperty(WSDL_URL, wsdlURL.toString());
+                setRefProperty(resource, ref.referenceName, naming, WSDL_URL, wsdlURL.toString());
             }
 
             // add port refs
@@ -478,15 +477,15 @@
                     portRef.getProperties().putAll(portRefInfo.properties);
                     portRefs.add(portRef);
                 }
-                setResource(resource, "port-refs", portRefs);
+                setResource(naming, resource, "port-refs", portRefs);
             }
 
             // add the handle chains
             if (!ref.handlerChains.isEmpty()) {
                 try {
                     List<HandlerChainData> handlerChains = WsBuilder.toHandlerChainData(ref.handlerChains, standardContext.getLoader().getClassLoader());
-                    setResource(resource, "handler-chains", handlerChains);
-                    setResource(resource, "injections", injections);
+                    setResource(naming, resource, "handler-chains", handlerChains);
+                    setResource(naming, resource, "injections", injections);
                 } catch (OpenEJBException e) {
                     throw new IllegalArgumentException("Error creating handler chain for web service-ref " + ref.referenceName);
                 }
@@ -542,23 +541,25 @@
         return wsdlUrl;
     }
 
-    private void setResource(ContextResource resource, String name, Object object) {
-        setStaticValue(new Resource(resource), name, object);
+    private void setResource(NamingResources naming, ContextResource resource, String name, Object object) {
+        setStaticValue(new Resource(naming, resource), name, object);
     }
 
-    private void setResource(ContextResource resource, Object object) {
-        setStaticValue(new Resource(resource), object);
+    private void setResource(NamingResources naming, ContextResource resource, Object object) {
+        setStaticValue(naming, new Resource(naming, resource), object);
     }
 
     private static class Resource implements NamingUtil.Resource {
+        private final NamingResources namingResources;
         private final ContextResource contextResource;
 
-        public Resource(ContextResource contextResource) {
+        private Resource(NamingResources namingResources, ContextResource contextResource) {
+            this.namingResources = namingResources;
             this.contextResource = contextResource;
         }
 
-        public void setProperty(String name, Object value) {
-            contextResource.setProperty(name, value);
+        public void setProperty(String name, String value) {
+            setRefProperty(contextResource, contextResource.getName(), namingResources, name, value);
         }
     }
 }
diff --git a/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/TomcatLoader.java b/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/TomcatLoader.java
index c441ecd..3290186 100644
--- a/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/TomcatLoader.java
+++ b/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/TomcatLoader.java
@@ -32,6 +32,7 @@
 import org.apache.openejb.util.LogCategory;
 import org.apache.openejb.tomcat.installer.Installer;
 import org.apache.openejb.tomcat.installer.Paths;
+import org.apache.openejb.tomcat.common.TomcatVersion;
 import org.apache.openejb.assembler.classic.WebAppBuilder;
 import org.apache.openejb.core.ServerFederation;
 import org.apache.openejb.core.ThreadContext;
@@ -142,6 +143,15 @@
             try {
                 ServerService serverService = (ServerService) Class.forName("org.apache.openejb.server.cxf.CxfService").newInstance();
                 serverService.start();
+            } catch (NoSuchMethodError e) {
+                Logger logger = Logger.getInstance(LogCategory.OPENEJB_STARTUP, getClass());
+                if (TomcatVersion.v50.isTheVersion()) {
+                    logger.warning("Webservices are disabled because Tomcat 5.0 includes an out dated XML parser.  " +
+                            "To enable webservices, simply delete 'common/endorsed/xercesImpl.jar' and " +
+                            "'common/endorsed/xml-apis.jar' in the Tomcat 5.0 installation directory");
+                } else {
+                    logger.warning("Webservices failed to start", e);
+                }
             } catch (ClassNotFoundException ignored) {
             } catch (Exception e) {
                 Logger logger = Logger.getInstance(LogCategory.OPENEJB_STARTUP, getClass());
@@ -205,16 +215,12 @@
                             if (hostChild instanceof StandardContext) {
                                 StandardContext standardContext = (StandardContext) hostChild;
                                 int state = standardContext.getState();
-                                if (state == 0) {
-                                    // context only initialized
-                                    tomcatWebAppBuilder.init(standardContext);
-                                } else if (state == 1) {
+                                if (state == 1) {
                                     // context already started
                                     standardContext.addParameter("openejb.start.late", "true");
                                     ClassLoader oldCL = Thread.currentThread().getContextClassLoader();
                                     Thread.currentThread().setContextClassLoader(standardContext.getLoader().getClassLoader());
                                     try {
-                                        tomcatWebAppBuilder.init(standardContext);
                                         tomcatWebAppBuilder.beforeStart(standardContext);
                                         tomcatWebAppBuilder.start(standardContext);
                                         tomcatWebAppBuilder.afterStart(standardContext);
diff --git a/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/TomcatWebAppBuilder.java b/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/TomcatWebAppBuilder.java
index f501b89..d03a6e7 100644
--- a/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/TomcatWebAppBuilder.java
+++ b/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/TomcatWebAppBuilder.java
@@ -27,6 +27,7 @@
 import org.apache.catalina.ServerFactory;
 import org.apache.catalina.Service;
 import org.apache.catalina.Wrapper;
+import org.apache.catalina.Valve;
 import org.apache.catalina.core.StandardContext;
 import org.apache.catalina.core.StandardHost;
 import org.apache.catalina.core.StandardServer;
@@ -171,6 +172,7 @@
                     contextInfo.appInfo = appInfo;
                     contextInfo.deployer = deployer;
                     contextInfo.standardContext = standardContext;
+                    // todo not a valid Tomcat6 method
                     deployer.manageApp(standardContext);
                 }
             }
@@ -183,6 +185,7 @@
             if (contextInfo != null && contextInfo.deployer != null) {
                 StandardContext standardContext = contextInfo.standardContext;
                 HostConfig deployer = contextInfo.deployer;
+                // todo not a valid Tomcat6 method
                 deployer.unmanageApp(standardContext.getPath());
                 deleteDir(new File(standardContext.getServletContext().getRealPath("")));
                 removeContextInfo(standardContext);
@@ -207,9 +210,6 @@
     // Tomcat Listener
     //
 
-    public void init(StandardContext standardContext) {
-    }
-
     public void beforeStart(StandardContext standardContext) {
     }
 
@@ -372,7 +372,7 @@
         }
 
 
-        OpenEJBValve openejbValve = new OpenEJBValve();
+        Valve openejbValve = BackportUtil.newOpenEJBValve();
         standardContext.getPipeline().addValve(openejbValve);
     }
 
@@ -396,15 +396,13 @@
         removeContextInfo(standardContext);
     }
 
-    public void destroy(StandardContext standardContext) {
-    }
-
     public void afterStop(StandardServer standardServer) {
         // clean ear based webapps after shutdown
         for (ContextInfo contextInfo : infos.values()) {
             if (contextInfo != null && contextInfo.deployer != null) {
                 StandardContext standardContext = contextInfo.standardContext;
                 HostConfig deployer = contextInfo.deployer;
+                // todo not a valid Tomcat6 method
                 deployer.unmanageApp(standardContext.getPath());
                 String realPath = standardContext.getServletContext().getRealPath("");
                 if (realPath != null) {
@@ -629,13 +627,15 @@
 
         // remove all jndi entries where there is a configured Tomcat resource or resource-link
         webApp = webModule.getWebApp();
-        for (ContextResource resource : naming.findResources()) {
-            String name = resource.getName();
-            removeRef(webApp, name);
-        }
-        for (ContextResourceLink resourceLink : naming.findResourceLinks()) {
-            String name = resourceLink.getName();
-            removeRef(webApp, name);
+        if (TomcatVersion.v55.isTheVersion() || TomcatVersion.v6.isTheVersion()) {
+            for (ContextResource resource : naming.findResources()) {
+                String name = resource.getName();
+                removeRef(webApp, name);
+            }
+            for (ContextResourceLink resourceLink : naming.findResourceLinks()) {
+                String name = resourceLink.getName();
+                removeRef(webApp, name);
+            }
         }
 
         // remove all env entries from the web xml that are not overridable
diff --git a/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/TomcatWsRegistry.java b/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/TomcatWsRegistry.java
index 7cbd549..2cb3315 100644
--- a/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/TomcatWsRegistry.java
+++ b/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/TomcatWsRegistry.java
@@ -31,7 +31,6 @@
 import org.apache.catalina.authenticator.DigestAuthenticator;
 import org.apache.catalina.authenticator.NonLoginAuthenticator;
 import org.apache.catalina.authenticator.SSLAuthenticator;
-import org.apache.catalina.connector.Connector;
 import org.apache.catalina.core.StandardContext;
 import org.apache.catalina.core.StandardServer;
 import org.apache.catalina.deploy.LoginConfig;
@@ -40,11 +39,11 @@
 import org.apache.openejb.server.httpd.HttpListener;
 import org.apache.openejb.server.webservices.WsRegistry;
 import org.apache.openejb.server.webservices.WsServlet;
+import org.apache.openejb.tomcat.catalina.BackportUtil.Connector;
 import static org.apache.openejb.tomcat.catalina.TomcatWebAppBuilder.IGNORE_CONTEXT;
 
 import java.net.URI;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 import java.util.TreeMap;
@@ -58,7 +57,7 @@
         StandardServer standardServer = (StandardServer) ServerFactory.getServer();
         for (Service service : standardServer.findServices()) {
             if (service.getContainer() instanceof Engine) {
-                connectors = Arrays.asList(service.findConnectors());
+                connectors = BackportUtil.findConnectors(service);
                 engine = (Engine) service.getContainer();
                 break;
             }
diff --git a/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/NamingUtil.java b/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/NamingUtil.java
index b8620be..d47cd82 100644
--- a/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/NamingUtil.java
+++ b/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/NamingUtil.java
@@ -18,6 +18,7 @@
 package org.apache.openejb.tomcat.common;
 
 import org.apache.naming.EjbRef;
+import org.apache.catalina.deploy.NamingResources;
 
 import javax.naming.RefAddr;
 import javax.naming.Reference;
@@ -61,7 +62,7 @@
         return Boolean.parseBoolean("" + value);
     }
 
-    public static void setStaticValue(Resource resource, Object value) {
+    public static void setStaticValue(NamingResources naming, Resource resource, Object value) {
         setStaticValue(resource, null, value);
     }
 
@@ -110,7 +111,7 @@
      * is not available in the common classloader in tomcat 55
      */
     public interface Resource {
-        void setProperty(String name, Object value);
+        void setProperty(String name, String value);
     }
 
 }
diff --git a/assembly/openejb-tomcat/openejb-tomcat-webapp/maven.xml b/assembly/openejb-tomcat/openejb-tomcat-webapp/maven.xml
index 399775d..434ab8e 100644
--- a/assembly/openejb-tomcat/openejb-tomcat-webapp/maven.xml
+++ b/assembly/openejb-tomcat/openejb-tomcat-webapp/maven.xml
@@ -99,6 +99,10 @@
       <copy todir="${tomcat.home}/conf">
         <fileset dir="${basedir}/src/test/conf"/>
       </copy>
+
+      <!-- Tomcat5 xml libraries don't work with cxf -->
+      <delete file="${tomcat.home}/common/endorsed/xercesImpl.jar"/>
+      <delete file="${tomcat.home}/common/endorsed/xml-apis.jar"/>
     </goal>
 
     <goal name="setup:tomcat-src">
diff --git a/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/installer-view.jsp b/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/installer-view.jsp
index dd84fee..6527314 100644
--- a/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/installer-view.jsp
+++ b/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/installer-view.jsp
@@ -24,6 +24,7 @@
 <%@ page import="org.apache.openejb.tomcat.installer.Paths" %>
 <%@ page import="java.util.List" %>
 <%@ page import="java.util.ArrayList" %>
+<%@ page import="java.util.Iterator" %>
 <%
     Installer installer = (Installer) request.getAttribute("installer");
     Paths paths = (Paths) request.getAttribute("paths");
@@ -95,7 +96,8 @@
                 <img border='0' height='3' width='360' src='images/line_light.gif'><br>
                 <table width='360' cellspacing='4' cellpadding='4' border='0'>
 <%
-        for (String info : installer.getInfos()) {
+        for (Iterator iterator = installer.getInfos().iterator(); iterator.hasNext();) {
+            String info = (String) iterator.next();
 %>
                     <tr>
                         <td><font size='2'><%= info %></font></td>
@@ -112,7 +114,7 @@
             Please, <b>restart Tomcat</b> and reload this page to verify installation.
 <%
         } else {
-            List<String> errors = new ArrayList<String>(paths.getErrors());
+            List errors = new ArrayList(paths.getErrors());
             errors.addAll(installer.getErrors());
             if (!errors.isEmpty()) {
 %>          Installation Failed<br><br>
@@ -120,7 +122,8 @@
                 <img border='0' height='3' width='360' src='images/line_light.gif'><br>
                 <table width='300' cellspacing='4' cellpadding='4' border='0'>
 <%
-                for (String error : errors) {
+            for (Iterator iterator = errors.iterator(); iterator.hasNext();) {
+                String error = (String) iterator.next();
 %>
                     <tr>
                         <td><font size='2'><%= error %></font></td>
diff --git a/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/invokeobj.jsp b/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/invokeobj.jsp
index 44bbace..0b799ba 100644
--- a/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/invokeobj.jsp
+++ b/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/invokeobj.jsp
@@ -193,7 +193,7 @@
      */
     public void printObjectList() throws Exception {
 
-        Map<String, Object> objects = getObjectMap();
+        Map objects = getObjectMap();
         if (objects.size() == 0) {
             out.print("<b>No object have been created</b><br>");
             out.print("<table>");
@@ -578,11 +578,10 @@
         getObjectMap().remove(objID);
     }
 
-    @SuppressWarnings({"unchecked"})
-    public Map<String, Object> getObjectMap() {
-        Map<String, Object> objects = (Map<String, Object>) session.getAttribute("objects");
+    public Map getObjectMap() {
+        Map objects = (Map) session.getAttribute("objects");
         if (objects == null) {
-            objects = new HashMap<String, Object>();
+            objects = new HashMap();
             session.setAttribute("objects", objects);
         }
         return objects;
@@ -592,18 +591,17 @@
     // Invocation list support
     /*-----------------------------------------------------------*/
     public Invocation getInvocation(String invID) {
-        return getInvocationMap().get(invID);
+        return (Invocation) getInvocationMap().get(invID);
     }
 
     public void setInvocation(String invID, Invocation obj) {
         getInvocationMap().put(invID, obj);
     }
 
-    @SuppressWarnings({"unchecked"})
-    public Map<String, Invocation> getInvocationMap() {
-        Map<String, Invocation> invocations = (Map<String, Invocation>) session.getAttribute("invocations");
+    public Map getInvocationMap() {
+        Map invocations = (Map) session.getAttribute("invocations");
         if (invocations == null) {
-            invocations = new HashMap<String, Invocation>();
+            invocations = new HashMap();
             session.setAttribute("invocations", invocations);
         }
         return invocations;
@@ -612,10 +610,10 @@
     /*-----------------------------------------------------------*/
     // String conversion support
     /*-----------------------------------------------------------*/
-    final Map<Class, Converter> converters = initConverters();
+    final Map converters = initConverters();
 
     public Converter getConverter(Class type) {
-        Converter con = converters.get(type);
+        Converter con = (Converter) converters.get(type);
         if (con == null) {
             con = defaultConverter;
         }
@@ -624,8 +622,8 @@
 
     final Converter defaultConverter = new ObjectConverter();
 
-    private Map<Class, Converter> initConverters() {
-        Map<Class, Converter> map = new HashMap<Class, Converter>();
+    private Map initConverters() {
+        Map map = new HashMap();
 
         map.put(String.class, new StringConverter());
         map.put(Character.class, new CharacterConverter());
diff --git a/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/testejb.jsp b/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/testejb.jsp
index a2bfe4b..fe5c060 100644
--- a/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/testejb.jsp
+++ b/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/testejb.jsp
@@ -187,7 +187,7 @@
                 Class[] params = new Class[0];
                 Method create = null;
                 create = homeInterface.getDeclaredMethod("create", params);
-                ejbObject = create.invoke(ejbHome);
+                ejbObject = create.invoke(ejbHome, new Object[0]);
 
                 if (ejbObject instanceof java.rmi.Remote) out.println(OK);
 
@@ -219,8 +219,8 @@
 
             Object returnValue = null;
             try {
-                Method businessMethod = remoteInterface.getDeclaredMethod("getMBeanCount");
-                returnValue = businessMethod.invoke(ejbObject);
+                Method businessMethod = remoteInterface.getDeclaredMethod("getMBeanCount", new Class[0]);
+                returnValue = businessMethod.invoke(ejbObject, new Object[0]);
 
                 if (returnValue instanceof java.lang.Integer) out.println(OK);
 
diff --git a/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/testint.jsp b/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/testint.jsp
index 0b70d4f..0963283 100644
--- a/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/testint.jsp
+++ b/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/testint.jsp
@@ -176,10 +176,10 @@
             printTest("Was OpenEJB initialized (aka started)");
 
             try {
-                Method isInitialized = openejb.getDeclaredMethod("isInitialized");
-                Boolean running = (Boolean) isInitialized.invoke(openejb);
+                Method isInitialized = openejb.getDeclaredMethod("isInitialized", new Class[0]);
+                Boolean running = (Boolean) isInitialized.invoke(openejb, new Object[0]);
 
-                if (running) {
+                if (running.booleanValue()) {
                     out.print(OK);
                 } else {
                     out.print(FAIL);
diff --git a/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/viewejb.jsp b/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/viewejb.jsp
index 870345f..b87502a 100644
--- a/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/viewejb.jsp
+++ b/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/viewejb.jsp
@@ -115,17 +115,17 @@
     private DeploymentInfo getDeployment(String id, javax.servlet.jsp.JspWriter out) {
         // due to crazy class loader stuff, we need to use reflection
         try {
-            Class<?> clazz = getClass().getClassLoader().getParent().getParent().loadClass("org.apache.openejb.loader.SystemInstance");
+            Class clazz = getClass().getClassLoader().getParent().getParent().loadClass("org.apache.openejb.loader.SystemInstance");
 //            out.print("clazz=" + clazz + "<br><br>");
 //            out.print("resource=" + clazz.getClassLoader().getResource("") + "<br><br>");
 
-            Method getMethod = clazz.getMethod("get");
+            Method getMethod = clazz.getMethod("get", new Class[0]);
 //            out.print("getMethod=" + getMethod + "<br><br>");
 
-            Object systemInstance = getMethod.invoke(null);
+            Object systemInstance = getMethod.invoke(null, new Object[0]);
 //            out.print("systemInstance=" + systemInstance + "<br><br>");
 
-            Method getComponentMethod = clazz.getMethod("getComponent", Class.class);
+            Method getComponentMethod = clazz.getMethod("getComponent", new Class[]{Class.class});
 //            out.print("getComponentMethod=" + getComponentMethod + "<br><br>");
 
 //            Field field = clazz.getDeclaredField("components");
@@ -133,7 +133,7 @@
 //            Object components = field.get(systemInstance);
 //            out.print("components=" + components + "<br><br>");
 
-            ContainerSystem containerSystem = (ContainerSystem) getComponentMethod.invoke(systemInstance, ContainerSystem.class);
+            ContainerSystem containerSystem = (ContainerSystem) getComponentMethod.invoke(systemInstance, new Object[]{ContainerSystem.class});
 //            out.print("containerSystem=" + containerSystem + "<br><br>");
             if (containerSystem == null) {
                 return null;
@@ -159,22 +159,17 @@
         }
         String type = null;
 
-        switch (ejb.getComponentType()) {
-            case CMP_ENTITY:
-                type = "EntityBean with Container-Managed Persistence";
-                break;
-            case BMP_ENTITY:
-                type = "EntityBean with Bean-Managed Persistence";
-                break;
-            case STATEFUL:
-                type = "Stateful SessionBean";
-                break;
-            case STATELESS:
-                type = "Stateless SessionBean";
-                break;
-            default:
-                type = "Unkown Bean Type";
-                break;
+        BeanType beanType = ejb.getComponentType();
+        if (beanType == BeanType.CMP_ENTITY) {
+            type = "EntityBean with Container-Managed Persistence";
+        } else if (beanType == BeanType.BMP_ENTITY) {
+            type = "EntityBean with Bean-Managed Persistence";
+        } else if (beanType == BeanType.STATEFUL) {
+            type = "Stateful SessionBean";
+        } else if (beanType == BeanType.STATELESS) {
+            type = "Stateless SessionBean";
+        } else {
+            type = "Unkown Bean Type";
         }
         out.print("<b>" + type + "</b><br>");
         out.print("<table>");
@@ -193,9 +188,9 @@
         // Browse JNDI with this ejb
         //javax.servlet.http.HttpSession session = this.session;
         //noinspection unchecked
-        Map<String, Object> objects = (Map<String, Object>) session.getAttribute("objects");
+        Map objects = (Map) session.getAttribute("objects");
         if (objects == null) {
-            objects = new HashMap<String, Object>();
+            objects = new HashMap();
             session.setAttribute("objects", objects);
         }
 
diff --git a/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/viewjndi.jsp b/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/viewjndi.jsp
index d9a2ab7..c3417f5 100644
--- a/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/viewjndi.jsp
+++ b/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/viewjndi.jsp
@@ -273,11 +273,11 @@
     }
 
     private Object getDeploymentId(Object ejb) throws Exception {
-        Class<?> proxyManagerClass = Class.forName("org.apache.openejb.util.proxy.ProxyManager");
-        Method getInvocationHandlerMethod = proxyManagerClass.getMethod("getInvocationHandler", Object.class);
-        Object handler = getInvocationHandlerMethod.invoke(null, ejb);
+        Class proxyManagerClass = Class.forName("org.apache.openejb.util.proxy.ProxyManager");
+        Method getInvocationHandlerMethod = proxyManagerClass.getMethod("getInvocationHandler", new Class[]{Object.class});
+        Object handler = getInvocationHandlerMethod.invoke(null, new Object[]{ejb});
 
-        Class<?> baseEjbProxyHandler = Class.forName("org.apache.openejb.core.ivm.BaseEjbProxyHandler");
+        Class baseEjbProxyHandler = Class.forName("org.apache.openejb.core.ivm.BaseEjbProxyHandler");
         Field field = baseEjbProxyHandler.getField("deploymentID");
         Object deploymentID = field.get(handler);
         return deploymentID;
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/core/ivm/naming/JaxWsServiceReference.java b/container/openejb-core/src/main/java/org/apache/openejb/core/ivm/naming/JaxWsServiceReference.java
index 38e24df..0c3b458 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/core/ivm/naming/JaxWsServiceReference.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/core/ivm/naming/JaxWsServiceReference.java
@@ -159,6 +159,9 @@
     private PortAddressRegistry getPortAddressRegistry() {
         if (portAddressRegistry == null) {
             portAddressRegistry = SystemInstance.get().getComponent(PortAddressRegistry.class);
+            if (portAddressRegistry == null) {
+                throw new IllegalStateException("Webservices have not been started");
+            }
         }
         return portAddressRegistry;
     }
diff --git a/container/openejb-loader/src/main/java/org/apache/openejb/loader/TomcatClassPath.java b/container/openejb-loader/src/main/java/org/apache/openejb/loader/TomcatClassPath.java
index 55cdb1e..ada61f5 100644
--- a/container/openejb-loader/src/main/java/org/apache/openejb/loader/TomcatClassPath.java
+++ b/container/openejb-loader/src/main/java/org/apache/openejb/loader/TomcatClassPath.java
@@ -101,6 +101,10 @@
 //        return commonLoader;
     }
 
+    public ClassLoader getCommonLoader() {
+        return commonLoader;
+    }
+
     public void addJarsToPath(File dir) throws Exception {
         String[] jarNames = dir.list(new java.io.FilenameFilter() {
             public boolean accept(File dir, String name) {
@@ -149,7 +153,7 @@
 
     protected void rebuild() {
         try {
-            sun.misc.URLClassPath cp = getURLClassPath((URLClassLoader) getClassLoader());
+            sun.misc.URLClassPath cp = getURLClassPath((URLClassLoader) getCommonLoader());
             URL[] urls = cp.getURLs();
 
             if (urls.length < 1)