You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by da...@apache.org on 2008/03/03 21:39:21 UTC

svn commit: r633268 [3/4] - in /openejb/trunk/openejb3: assembly/openejb-tomcat/ assembly/openejb-tomcat/openejb-tomcat-catalina/ assembly/openejb-tomcat/openejb-tomcat-catalina/src/ assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/ assembly/op...

Added: openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/TomcatWebAppBuilder.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/TomcatWebAppBuilder.java?rev=633268&view=auto
==============================================================================
--- openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/TomcatWebAppBuilder.java (added)
+++ openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/TomcatWebAppBuilder.java Mon Mar  3 12:39:06 2008
@@ -0,0 +1,772 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.openejb.tomcat.catalina;
+
+import static org.apache.openejb.tomcat.catalina.BackportUtil.getServlet;
+import static org.apache.openejb.tomcat.catalina.BackportUtil.*;
+import org.apache.openejb.tomcat.common.LegacyAnnotationProcessor;
+import org.apache.openejb.tomcat.common.TomcatVersion;
+import org.apache.catalina.Container;
+import org.apache.catalina.Engine;
+import org.apache.catalina.LifecycleListener;
+import org.apache.catalina.ServerFactory;
+import org.apache.catalina.Service;
+import org.apache.catalina.Wrapper;
+import org.apache.catalina.core.StandardContext;
+import org.apache.catalina.core.StandardHost;
+import org.apache.catalina.core.StandardServer;
+import org.apache.catalina.core.ContainerBase;
+import org.apache.catalina.deploy.ContextEnvironment;
+import org.apache.catalina.deploy.ContextResource;
+import org.apache.catalina.deploy.ContextResourceLink;
+import org.apache.catalina.deploy.NamingResources;
+import org.apache.catalina.startup.ContextConfig;
+import org.apache.catalina.startup.HostConfig;
+import org.apache.naming.ContextAccessController;
+import org.apache.naming.ContextBindings;
+import org.apache.openejb.OpenEJBException;
+import org.apache.openejb.Injection;
+import org.apache.openejb.spi.ContainerSystem;
+import org.apache.openejb.server.webservices.WsServlet;
+import org.apache.openejb.assembler.classic.AppInfo;
+import org.apache.openejb.assembler.classic.Assembler;
+import org.apache.openejb.util.LinkResolver;
+import org.apache.openejb.assembler.classic.WebAppBuilder;
+import org.apache.openejb.assembler.classic.WebAppInfo;
+import org.apache.openejb.assembler.classic.EjbJarInfo;
+import org.apache.openejb.assembler.classic.ConnectorInfo;
+import org.apache.openejb.assembler.classic.InjectionBuilder;
+import org.apache.openejb.config.AnnotationDeployer;
+import org.apache.openejb.config.AppModule;
+import org.apache.openejb.config.ConfigurationFactory;
+import org.apache.openejb.config.DeploymentLoader;
+import org.apache.openejb.config.EjbModule;
+import org.apache.openejb.config.ReadDescriptors;
+import org.apache.openejb.config.UnknownModuleTypeException;
+import org.apache.openejb.config.WebModule;
+import org.apache.openejb.core.ivm.naming.SystemComponentReference;
+import org.apache.openejb.core.webservices.JaxWsUtils;
+import org.apache.openejb.core.CoreWebDeploymentInfo;
+import org.apache.openejb.core.CoreContainerSystem;
+import org.apache.openejb.core.TemporaryClassLoader;
+import org.apache.openejb.jee.EnvEntry;
+import org.apache.openejb.jee.WebApp;
+import org.apache.openejb.loader.SystemInstance;
+import org.apache.openejb.util.LogCategory;
+import org.apache.openejb.util.Logger;
+import org.apache.xbean.finder.ResourceFinder;
+import org.apache.xbean.finder.UrlSet;
+import org.omg.CORBA.ORB;
+
+import javax.ejb.spi.HandleDelegate;
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.persistence.EntityManagerFactory;
+import javax.servlet.ServletContext;
+import javax.transaction.TransactionManager;
+import javax.transaction.TransactionSynchronizationRegistry;
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.HashMap;
+import java.util.Iterator;
+
+public class TomcatWebAppBuilder implements WebAppBuilder, ContextListener {
+    public static final String IGNORE_CONTEXT = TomcatWebAppBuilder.class.getName() + ".IGNORE";
+    private static final Logger logger = Logger.getInstance(LogCategory.OPENEJB.createChild("tomcat"), "org.apache.openejb.util.resources");
+
+    private final TreeMap<String, ContextInfo> infos = new TreeMap<String, ContextInfo>();
+    private final GlobalListenerSupport globalListenerSupport;
+    private final ConfigurationFactory configurationFactory;
+    private final Map<String,HostConfig> deployers = new TreeMap<String,HostConfig>();
+    // todo merge this map witth the infos map above
+    private final Map<String,DeployedApplication> deployedApps = new TreeMap<String,DeployedApplication>();
+    private final DeploymentLoader deploymentLoader;
+    private Assembler assembler;
+    private CoreContainerSystem containerSystem;
+
+    public TomcatWebAppBuilder() {
+        StandardServer standardServer = (StandardServer) ServerFactory.getServer();
+        globalListenerSupport = new GlobalListenerSupport(standardServer, this);
+
+        for (Service service : standardServer.findServices()) {
+            if (service.getContainer() instanceof Engine) {
+                Engine engine = (Engine) service.getContainer();
+                for (Container engineChild : engine.findChildren()) {
+                    if (engineChild instanceof StandardHost) {
+                        StandardHost host = (StandardHost) engineChild;
+                        for (LifecycleListener listener : host.findLifecycleListeners()) {
+                            if (listener instanceof HostConfig) {
+                                HostConfig hostConfig = (HostConfig) listener;
+                                deployers.put(host.getName(), hostConfig);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        // MBeanServer mbeanServer;
+        // List mbeanServers = MBeanServerFactory.findMBeanServer(null);
+        // if (mbeanServers.size() > 0) {
+        //     mbeanServer = (MBeanServer) mbeanServers.get(0);
+        // } else {
+        //     mbeanServer = MBeanServerFactory.createMBeanServer();
+        // }
+
+        configurationFactory = new ConfigurationFactory();
+        deploymentLoader = new DeploymentLoader();
+        assembler = (Assembler) SystemInstance.get().getComponent(org.apache.openejb.spi.Assembler.class);
+        containerSystem = (CoreContainerSystem) SystemInstance.get().getComponent(ContainerSystem.class);
+    }
+
+    public void start() {
+        globalListenerSupport.start();
+
+    }
+
+    public void stop() {
+        globalListenerSupport.stop();
+    }
+
+    //
+    // OpenEJB WebAppBuilder
+    //
+
+    public void deployWebApps(AppInfo appInfo, ClassLoader classLoader) throws Exception {
+        for (WebAppInfo webApp : appInfo.webApps) {
+            if (getContextInfo(webApp) == null) {
+                StandardContext standardContext = new StandardContext();
+                standardContext.addLifecycleListener(new ContextConfig());
+                standardContext.setPath("/" + webApp.contextRoot);
+                standardContext.setDocBase(webApp.codebase);
+                standardContext.setParentClassLoader(classLoader);
+                standardContext.setDelegate(true);
+
+                String host = webApp.host;
+                if (host == null) host = "localhost";
+                HostConfig deployer = deployers.get(host);
+                if (deployer != null) {
+                    // host isn't set until we call deployer.manageApp, so pass it
+                    ContextInfo contextInfo = addContextInfo(host, standardContext);
+                    contextInfo.appInfo = appInfo;
+                    contextInfo.deployer = deployer;
+                    contextInfo.standardContext = standardContext;
+                    deployer.manageApp(standardContext);
+                }
+            }
+        }
+    }
+
+    public void undeployWebApps(AppInfo appInfo) throws Exception {
+        for (WebAppInfo webApp : appInfo.webApps) {
+            ContextInfo contextInfo = getContextInfo(webApp);
+            if (contextInfo != null && contextInfo.deployer != null) {
+                StandardContext standardContext = contextInfo.standardContext;
+                HostConfig deployer = contextInfo.deployer;
+                deployer.unmanageApp(standardContext.getPath());
+                deleteDir(new File(standardContext.getServletContext().getRealPath("")));
+                removeContextInfo(standardContext);
+            }
+        }
+    }
+
+    private void deleteDir(File dir) {
+        if (dir == null) return;
+        if (dir.isFile()) return;
+        for (File file : dir.listFiles()) {
+            if (file.isDirectory()) {
+                deleteDir(file);
+            } else {
+                file.delete();
+            }
+        }
+        dir.delete();
+    }
+
+    //
+    // Tomcat Listener
+    //
+
+    public void init(StandardContext standardContext) {
+    }
+
+    public void beforeStart(StandardContext standardContext) {
+    }
+
+    // context class loader is now defined, but no classes should have been loaded
+    public void start(StandardContext standardContext) {
+        if (standardContext.getServletContext().getAttribute(IGNORE_CONTEXT) != null) return;
+
+        Assembler assembler = getAssembler();
+        if (assembler == null) {
+            logger.warning("OpenEJB has not been initialized so war will not be scanned for nested modules " + standardContext.getPath());
+            return;
+        }
+
+        ContextInfo contextInfo = getContextInfo(standardContext);
+        if (contextInfo == null) {
+            AppModule appModule = loadApplication(standardContext);
+            if (appModule != null) {
+                try {
+                    contextInfo = addContextInfo(standardContext.getHostname(), standardContext);
+                    AppInfo appInfo = configurationFactory.configureApplication(appModule);
+                    contextInfo.appInfo = appInfo;
+
+                    assembler.createApplication(contextInfo.appInfo, standardContext.getLoader().getClassLoader());
+                    // todo add watched resources to context
+                } catch (Exception e) {
+                    logger.error("Unable to deploy collapsed ear in war " + standardContext.getPath() + ": Exception: " + e.getMessage(), e);
+                }
+            }
+        }
+
+        contextInfo.standardContext = standardContext;
+
+        WebAppInfo webAppInfo = null;
+        // appInfo is null when deployment fails
+        if (contextInfo.appInfo != null) {
+            for (WebAppInfo w : contextInfo.appInfo.webApps) {
+                if (("/" + w.contextRoot).equals(standardContext.getPath())) {
+                    webAppInfo = w;
+                    break;
+                }
+            }
+        }
+
+        if (webAppInfo != null) {
+            try {
+                // determind the injections
+                InjectionBuilder injectionBuilder = new InjectionBuilder(standardContext.getLoader().getClassLoader());
+                List<Injection> injections = injectionBuilder.buildInjections(webAppInfo.jndiEnc);
+
+                // merge OpenEJB jndi into Tomcat jndi
+                TomcatJndiBuilder jndiBuilder = new TomcatJndiBuilder(standardContext, webAppInfo, injections);
+                jndiBuilder.mergeJndi();
+
+                // add WebDeploymentInfo to ContainerSystem
+                CoreWebDeploymentInfo webDeploymentInfo = new CoreWebDeploymentInfo();
+                webDeploymentInfo.setId(webAppInfo.moduleId);
+                webDeploymentInfo.setClassLoader(standardContext.getLoader().getClassLoader());
+                webDeploymentInfo.getInjections().addAll(injections);
+                getContainerSystem().addWebDeployment(webDeploymentInfo);
+            } catch (Exception e) {
+                logger.error("Error merging OpenEJB JNDI entries in to war " + standardContext.getPath() + ": Exception: " + e.getMessage(), e);
+            }
+        }
+    }
+
+    public void afterStart(StandardContext standardContext) {
+        if (standardContext.getServletContext().getAttribute(IGNORE_CONTEXT) != null) return;
+
+        // if appInfo is null this is a failed deployment... just ignore
+        ContextInfo contextInfo = getContextInfo(standardContext);
+        if (contextInfo.appInfo == null) return;
+
+        // replace any webservices with the webservice servlet
+        // HACK: use a temp class loader because the class may have been loaded before
+        // the openejb classes were added to the system class path so the WebService anntation
+        // will not be present on the class
+        TemporaryClassLoader tempClassLoader = new TemporaryClassLoader(standardContext.getLoader().getClassLoader());
+        for (Container container : standardContext.findChildren()) {
+            if (container instanceof Wrapper) {
+                Wrapper wrapper = (Wrapper) container;
+                String servletClass = wrapper.getServletClass();
+                try {
+                    Class<?> clazz = tempClassLoader.loadClass(servletClass);
+                    if (JaxWsUtils.isWebService(clazz)) {
+                        wrapper.setServletClass(WsServlet.class.getName());
+                        if (getServlet(wrapper) != null) {
+                            wrapper.load();
+                            wrapper.unload();
+                        }
+                    }
+                } catch (Exception e) {
+                    // will be reported by the tomcat
+                }
+            }
+        }
+
+        // bind extra stuff at the java:comp level which can only be
+        // bound after the context is created
+        String listenerName = getNamingContextListener(standardContext).getName();
+        ContextAccessController.setWritable(listenerName, standardContext);
+        try {
+
+            Context openejbContext = SystemInstance.get().getComponent(ContainerSystem.class).getJNDIContext();
+            openejbContext = (Context) openejbContext.lookup("openejb");
+
+            Context root = (Context) ContextBindings.getClassLoader().lookup("");
+            safeBind(root, "openejb", openejbContext);
+
+            Context comp = (Context) ContextBindings.getClassLoader().lookup("comp");
+
+            // add context to WebDeploymentInfo
+            for (WebAppInfo webAppInfo : contextInfo.appInfo.webApps) {
+                if (("/" + webAppInfo.contextRoot).equals(standardContext.getPath())) {
+                    CoreWebDeploymentInfo webDeploymentInfo = (CoreWebDeploymentInfo) getContainerSystem().getWebDeploymentInfo(webAppInfo.moduleId);
+                    if (webDeploymentInfo != null) {
+                        webDeploymentInfo.setJndiEnc(comp);
+                    }
+                    break;
+                }
+            }
+
+            // bind TransactionManager
+            TransactionManager transactionManager = SystemInstance.get().getComponent(TransactionManager.class);
+            safeBind(comp, "TransactionManager", transactionManager);
+
+            // bind TransactionSynchronizationRegistry
+            TransactionSynchronizationRegistry synchronizationRegistry = SystemInstance.get().getComponent(TransactionSynchronizationRegistry.class);
+            safeBind(comp, "TransactionSynchronizationRegistry", synchronizationRegistry);
+
+            safeBind(comp, "ORB", new SystemComponentReference(ORB.class));
+            safeBind(comp, "HandleDelegate", new SystemComponentReference(HandleDelegate.class));
+        } catch (NamingException e) {
+        }
+        ContextAccessController.setReadOnly(listenerName);
+
+        if (!TomcatVersion.hasAnnotationProcessingSupport()){
+            try {
+                Context compEnv = (Context) ContextBindings.getClassLoader().lookup("comp/env");
+
+                LegacyAnnotationProcessor annotationProcessor = new LegacyAnnotationProcessor(compEnv);
+
+                standardContext.addContainerListener(new ProcessAnnotatedListenersListener(annotationProcessor));
+
+                for (Container container : standardContext.findChildren()) {
+                    if (container instanceof Wrapper) {
+                        Wrapper wrapper = (Wrapper) container;
+                        wrapper.addInstanceListener(new ProcessAnnotatedServletsListener(annotationProcessor));
+                    }
+                }
+            } catch (NamingException e) {
+            }
+        }
+
+
+        OpenEJBValve openejbValve = new OpenEJBValve();
+        standardContext.getPipeline().addValve(openejbValve);
+    }
+
+    public void beforeStop(StandardContext standardContext) {
+    }
+
+    public void stop(StandardContext standardContext) {
+    }
+
+    public void afterStop(StandardContext standardContext) {
+        if (standardContext.getServletContext().getAttribute(IGNORE_CONTEXT) != null) return;
+
+        ContextInfo contextInfo = getContextInfo(standardContext);
+        if (contextInfo != null && contextInfo.appInfo != null && contextInfo.deployer == null) {
+            try {
+                assembler.destroyApplication(contextInfo.appInfo.jarPath);
+            } catch (Exception e) {
+                logger.error("Unable to stop web application " + standardContext.getPath() + ": Exception: " + e.getMessage(), e);
+            }
+        }
+        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;
+                deployer.unmanageApp(standardContext.getPath());
+                String realPath = standardContext.getServletContext().getRealPath("");
+                if (realPath != null) {
+                    deleteDir(new File(realPath));
+                }
+            }
+        }
+    }
+
+    public void checkHost(StandardHost standardHost) {
+        if (standardHost.getAutoDeploy()) {
+            // Undeploy any modified application
+            for (Iterator<Map.Entry<String, DeployedApplication>> iterator = deployedApps.entrySet().iterator(); iterator.hasNext();) {
+                Map.Entry<String, DeployedApplication> entry = iterator.next();
+                DeployedApplication deployedApplication = entry.getValue();
+                if (deployedApplication.isModified()) {
+                    try {
+                        assembler.destroyApplication(deployedApplication.appInfo.jarPath);
+                    } catch (Exception e) {
+                        logger.error("Unable to application " + deployedApplication.appInfo.jarPath + ": Exception: " + e.getMessage(), e);
+                    }
+                    iterator.remove();
+                }
+            }
+
+            // Deploy new applications
+            File appBase = appBase(standardHost);
+            File[] files = appBase.listFiles();
+            for (File file : files) {
+                String name = file.getName();
+                if (name.toLowerCase().endsWith(".war") || name.equals("ROOT") || name.equalsIgnoreCase("META-INF") || name.equalsIgnoreCase("WEB-INF")) continue;
+                if (file.isDirectory() && new File(file, "WEB-INF").exists()) continue;
+                if (isDeployed(file, standardHost)) continue;
+
+                AppInfo appInfo = null;
+                try {
+                    file = file.getCanonicalFile().getAbsoluteFile();
+
+                    AppModule appModule = deploymentLoader.load(file);
+
+                    // Ignore any standalone web modules - this happens when the app is unpaked and doesn't have a WEB-INF dir
+                    if (appModule.getDeploymentModule().size() == 1 && appModule.getWebModules().size() == 1) {
+                        WebModule webModule = appModule.getWebModules().iterator().next();
+                        if (file.getAbsolutePath().equals(webModule.getJarLocation())) {
+                            continue;
+                        }
+                    }
+
+                    // if this is an unpacked dir, tomcat will pick it up as a webapp so undeploy it first
+                    if (file.isDirectory()) {
+                        ContainerBase context = (ContainerBase) standardHost.findChild("/" + name);
+                        if (context != null) {
+                            try {
+                                standardHost.removeChild(context);
+                            } catch (Throwable t) {
+                                logger.warning("Error undeploying wep application from Tomcat  " + name, t);
+                            }
+                            try {
+                                context.destroy();
+                            } catch (Throwable t) {
+                                logger.warning("Error destroying Tomcat web context " + name, t);
+                            }
+                        }
+                    }
+
+                    // tell web modules to deploy using this host
+                    for (WebModule webModule : appModule.getWebModules()) {
+                        webModule.setHost(standardHost.getName());
+                    }
+
+                    appInfo = configurationFactory.configureApplication(appModule);
+                    assembler.createApplication(appInfo);
+                } catch (Throwable e) {
+                    logger.warning("Error deploying application " + file.getAbsolutePath(), e);
+                }
+                deployedApps.put(file.getAbsolutePath(), new DeployedApplication(file, appInfo));
+            }
+        }
+    }
+
+    private boolean isDeployed(File file, StandardHost standardHost) {
+        if (deployedApps.containsKey(file.getAbsolutePath())) {
+            return true;
+        }
+
+        // check if this is a deployed web application
+        String name = "/" + file.getName();
+
+        // ROOT context is a special case
+        if (name.equals("/ROOT")) name = "";
+
+        return file.isFile() && standardHost.findChild(name) != null;
+    }
+
+    protected File appBase(StandardHost standardHost) {
+        File file = new File(standardHost.getAppBase());
+        if (!file.isAbsolute()) {
+            file = new File(System.getProperty("catalina.base"), standardHost.getAppBase());
+        }
+        try {
+            file= file.getCanonicalFile();
+        } catch (IOException e) {
+        }
+        return file;
+    }
+
+    private AppModule loadApplication(StandardContext standardContext) {
+        // create the web module
+        WebModule webModule = createWebModule(standardContext);
+
+        // create the app module
+        AppModule appModule = new AppModule(webModule.getClassLoader(), webModule.getJarLocation());
+
+        // add the web module itself
+        appModule.getWebModules().add(webModule);
+
+        // check each url to determine if it is an ejb jar
+        for (URL url : getUrls(standardContext)) {
+            try {
+                Class moduleType = DeploymentLoader.discoverModuleType(url, standardContext.getLoader().getClassLoader(), true);
+                if (EjbModule.class.isAssignableFrom(moduleType)) {
+                    File file;
+                    if (url.getProtocol().equals("jar")) {
+                        url = new URL(url.getFile().replaceFirst("!.*$", ""));
+                        file = new File(url.getFile());
+                    } else if (url.getProtocol().equals("file")) {
+                        file = new File(url.getFile());
+                    } else {
+                        logger.warning("Not loading " + moduleType.getSimpleName() + ".  Unknown protocol " + url.getProtocol());
+                        continue;
+                    }
+
+                    logger.info("Found ejb module " + moduleType.getSimpleName() + " in war " + standardContext.getPath());
+
+                    // creat the module
+                    EjbModule ejbModule = new EjbModule(webModule.getClassLoader(), file.getAbsolutePath(), null, null);
+
+                    // EJB deployment descriptors
+                    try {
+                        ResourceFinder ejbResourceFinder = new ResourceFinder("", standardContext.getLoader().getClassLoader(), file.toURL());
+                        Map<String, URL> descriptors = ejbResourceFinder.getResourcesMap("META-INF/");
+                        ejbModule.getAltDDs().putAll(descriptors);
+                    } catch (IOException e) {
+                        logger.error("Unable to determine descriptors in jar.", e);
+                    }
+
+                    // add module to app
+                    appModule.getEjbModules().add(ejbModule);
+                }
+            } catch (IOException e) {
+                logger.warning("Unable to determine the module type of " + url.toExternalForm() + ": Exception: " + e.getMessage(), e);
+            } catch (UnknownModuleTypeException ignore) {
+            }
+
+        }
+
+        // Persistence Units via META-INF/persistence.xml
+        try {
+            ResourceFinder finder = new ResourceFinder("", standardContext.getLoader().getClassLoader());
+            List<URL> persistenceUrls = finder.findAll("META-INF/persistence.xml");
+            appModule.getAltDDs().put("persistence.xml", persistenceUrls);
+        } catch (IOException e) {
+            logger.warning("Cannot load persistence-units from 'META-INF/persistence.xml' : " + e.getMessage(), e);
+        }
+
+        return appModule;
+    }
+
+    private WebModule createWebModule(StandardContext standardContext) {
+        ServletContext servletContext = standardContext.getServletContext();
+
+        // read the web.xml
+        WebApp webApp = new WebApp();
+        try {
+            URL webXmlUrl = servletContext.getResource("/WEB-INF/web.xml");
+            if (webXmlUrl != null) {
+                webApp = ReadDescriptors.readWebApp(webXmlUrl);
+            }
+        } catch (Exception e) {
+            logger.error("Unable to load web.xml in war " + standardContext.getPath() + ": Exception: " + e.getMessage(), e);
+        }
+
+        // create the web module
+        String basePath = new File(servletContext.getRealPath(".")).getParentFile().getAbsolutePath();
+        ClassLoader classLoader = new TemporaryClassLoader(standardContext.getLoader().getClassLoader());
+        String path = standardContext.getPath();
+        System.out.println("context path = " + path);
+        WebModule webModule = new WebModule(webApp, path, classLoader, basePath, getId(standardContext));
+        webModule.setHost(standardContext.getHostname());
+
+        // Add all Tomcat env entries to context so they can be overriden by the env.properties file
+        NamingResources naming = standardContext.getNamingResources();
+        for (ContextEnvironment environment : naming.findEnvironments()) {
+            EnvEntry envEntry = webApp.getEnvEntryMap().get(environment.getName());
+            if (envEntry == null) {
+                envEntry = new EnvEntry();
+                envEntry.setName(environment.getName());
+                webApp.getEnvEntry().add(envEntry);
+            }
+
+            envEntry.setEnvEntryValue(environment.getValue());
+            envEntry.setEnvEntryType(environment.getType());
+        }
+
+        // process the annotations
+        try {
+            AnnotationDeployer annotationDeployer = new AnnotationDeployer();
+            annotationDeployer.deploy(webModule);
+        } catch (OpenEJBException e) {
+            logger.error("Unable to process annotation in " + standardContext.getPath() + ": Exception: " + e.getMessage(), e);
+        }
+
+        // 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);
+        }
+
+        // remove all env entries from the web xml that are not overridable
+        for (ContextEnvironment environment : naming.findEnvironments()) {
+            if (!environment.getOverride()) {
+                // overrides are not allowed
+                webApp.getEnvEntryMap().remove(environment.getName());
+            }
+        }
+
+        return webModule;
+    }
+
+    private void removeRef(WebApp webApp, String name) {
+        webApp.getEnvEntryMap().remove(name);
+        webApp.getEjbRefMap().remove(name);
+        webApp.getEjbLocalRefMap().remove(name);
+        webApp.getMessageDestinationRefMap().remove(name);
+        webApp.getPersistenceContextRefMap().remove(name);
+        webApp.getPersistenceUnitRefMap().remove(name);
+        webApp.getResourceRefMap().remove(name);
+        webApp.getResourceEnvRefMap().remove(name);
+    }
+
+    private List<URL> getUrls(StandardContext standardContext) {
+        List<URL> urls = null;
+        try {
+            ClassLoader classLoader = standardContext.getLoader().getClassLoader();
+            UrlSet urlSet = new UrlSet(classLoader);
+            urlSet = urlSet.exclude(classLoader.getParent());
+            urls = urlSet.getUrls();
+        } catch (IOException e) {
+            logger.warning("Unable to determine URLs in web application " + standardContext.getPath(), e);
+        }
+        return urls;
+    }
+
+    //
+    // helper methods
+    //
+
+    private void safeBind(Context comp, String name, Object value) {
+        try {
+            comp.bind(name, value);
+        } catch (NamingException e) {
+        }
+    }
+
+    private Assembler getAssembler() {
+        if (assembler == null) {
+            assembler = (Assembler) SystemInstance.get().getComponent(org.apache.openejb.spi.Assembler.class);
+        }
+        return assembler;
+    }
+
+    private CoreContainerSystem getContainerSystem() {
+        if (containerSystem == null) {
+            containerSystem = (CoreContainerSystem) SystemInstance.get().getComponent(ContainerSystem.class);
+        }
+        return containerSystem;
+    }
+
+    private String getId(StandardContext standardContext) {
+        String contextRoot = standardContext.getName();
+        if (!contextRoot.startsWith("/")) contextRoot = "/" + contextRoot;
+        return standardContext.getHostname() + contextRoot;
+    }
+
+    private ContextInfo getContextInfo(StandardContext standardContext) {
+        String id = getId(standardContext);
+        ContextInfo contextInfo = infos.get(id);
+        return contextInfo;
+    }
+
+    private ContextInfo getContextInfo(WebAppInfo webAppInfo) {
+        String host = webAppInfo.host;
+        if (host == null) host = "localhost";
+        String contextRoot = webAppInfo.contextRoot;
+        String id = host + "/" + contextRoot;
+        ContextInfo contextInfo = infos.get(id);
+        return contextInfo;
+    }
+
+    private ContextInfo addContextInfo(String host, StandardContext standardContext) {
+        String contextRoot = standardContext.getName();
+        if (!contextRoot.startsWith("/")) contextRoot = "/" + contextRoot;
+        String id = host + contextRoot;
+        ContextInfo contextInfo = infos.get(id);
+        if (contextInfo == null) {
+            contextInfo = new ContextInfo();
+            infos.put(id, contextInfo);
+        }
+        return contextInfo;
+    }
+
+    private void removeContextInfo(StandardContext standardContext) {
+        String id = getId(standardContext);
+        infos.remove(id);
+    }
+
+    private static class ContextInfo {
+        public AppInfo appInfo;
+        public StandardContext standardContext;
+        public HostConfig deployer;
+        public LinkResolver<EntityManagerFactory> emfLinkResolver;
+    }
+
+    private static class DeployedApplication {
+        private AppInfo appInfo;
+        private final Map<File,Long> watchedResource = new HashMap<File,Long>();
+
+        public DeployedApplication(File base, AppInfo appInfo) {
+            this.appInfo = appInfo;
+            watchedResource.put(base, base.lastModified());
+            if (appInfo != null) {
+                for (String resource : appInfo.watchedResources) {
+                    File file = new File(resource);
+                    watchedResource.put(file, file.lastModified());
+                }
+                for (EjbJarInfo info : appInfo.ejbJars) {
+                    for (String resource : info.watchedResources) {
+                        File file = new File(resource);
+                        watchedResource.put(file, file.lastModified());
+                    }
+                }
+                for (WebAppInfo info : appInfo.webApps) {
+                    for (String resource : info.watchedResources) {
+                        File file = new File(resource);
+                        watchedResource.put(file, file.lastModified());
+                    }
+                }
+                for (ConnectorInfo info : appInfo.connectors) {
+                    for (String resource : info.watchedResources) {
+                        File file = new File(resource);
+                        watchedResource.put(file, file.lastModified());
+                    }
+                }
+            }
+        }
+
+        public boolean isModified() {
+            for (Map.Entry<File, Long> entry : watchedResource.entrySet()) {
+                File file = entry.getKey();
+                long lastModified = entry.getValue();
+                if ((!file.exists() && lastModified != 0L) ||
+                        (file.lastModified() != lastModified)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+}

Added: openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/TomcatWsRegistry.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/TomcatWsRegistry.java?rev=633268&view=auto
==============================================================================
--- openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/TomcatWsRegistry.java (added)
+++ openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/java/org/apache/openejb/tomcat/catalina/TomcatWsRegistry.java Mon Mar  3 12:39:06 2008
@@ -0,0 +1,255 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.openejb.tomcat.catalina;
+
+import org.apache.catalina.Container;
+import org.apache.catalina.Context;
+import org.apache.catalina.Engine;
+import org.apache.catalina.Host;
+import org.apache.catalina.Lifecycle;
+import org.apache.catalina.LifecycleEvent;
+import org.apache.catalina.LifecycleListener;
+import org.apache.catalina.ServerFactory;
+import org.apache.catalina.Service;
+import org.apache.catalina.Wrapper;
+import org.apache.catalina.authenticator.BasicAuthenticator;
+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;
+import org.apache.catalina.deploy.SecurityCollection;
+import org.apache.catalina.deploy.SecurityConstraint;
+import org.apache.openejb.server.httpd.HttpListener;
+import org.apache.openejb.server.webservices.WsRegistry;
+import org.apache.openejb.server.webservices.WsServlet;
+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;
+
+public class TomcatWsRegistry implements WsRegistry {
+    private final Map<String, StandardContext> webserviceContexts = new TreeMap<String, StandardContext>();
+    private Engine engine;
+    private List<Connector> connectors;
+
+    public TomcatWsRegistry() {
+        StandardServer standardServer = (StandardServer) ServerFactory.getServer();
+        for (Service service : standardServer.findServices()) {
+            if (service.getContainer() instanceof Engine) {
+                connectors = Arrays.asList(service.findConnectors());
+                engine = (Engine) service.getContainer();
+                break;
+            }
+        }
+    }
+
+    public List<String> setWsContainer(String virtualHost, String contextRoot, String servletName, HttpListener wsContainer) throws Exception {
+        if (virtualHost == null) virtualHost = engine.getDefaultHost();
+
+        Container host = engine.findChild(virtualHost);
+        if (host == null) {
+            throw new IllegalArgumentException("Invalid virtual host '" + virtualHost + "'.  Do you have a matchiing Host entry in the server.xml?");
+        }
+
+        Context context = (Context) host.findChild("/" + contextRoot);
+        if (context == null) {
+            throw new IllegalArgumentException("Could not find web application context " + contextRoot + " in host " + host.getName());
+        }
+
+        Wrapper wrapper = (Wrapper) context.findChild(servletName);
+        if (wrapper == null) {
+            throw new IllegalArgumentException("Could not find servlet " + contextRoot + " in web application context " + context.getName());
+        }
+
+        setWsContainer(context, wrapper, wsContainer);
+
+        // add service locations
+        List<String> addresses = new ArrayList<String>();
+        for (Connector connector : connectors) {
+            for (String mapping : wrapper.findMappings()) {
+                URI address = new URI(connector.getScheme(), null, host.getName(), connector.getPort(), "/" + contextRoot + mapping, null, null);
+                addresses.add(address.toString());
+            }
+        }
+        return addresses;
+    }
+
+    public void clearWsContainer(String virtualHost, String contextRoot, String servletName) {
+        if (virtualHost == null) virtualHost = engine.getDefaultHost();
+
+        Container host = engine.findChild(virtualHost);
+        if (host == null) {
+            throw new IllegalArgumentException("Invalid virtual host '" + virtualHost + "'.  Do you have a matchiing Host entry in the server.xml?");
+        }
+
+        Context context = (Context) host.findChild("/" + contextRoot);
+        if (context == null) {
+            throw new IllegalArgumentException("Could not find web application context " + contextRoot + " in host " + host.getName());
+        }
+
+        Wrapper wrapper = (Wrapper) context.findChild(servletName);
+        if (wrapper == null) {
+            throw new IllegalArgumentException("Could not find servlet " + contextRoot + " in web application context " + context.getName());
+        }
+
+        // clear the webservice ref in the servlet context
+        String webServicecontainerId = wrapper.findInitParameter(WsServlet.WEBSERVICE_CONTAINER);
+        if (webServicecontainerId != null) {
+            context.getServletContext().removeAttribute(webServicecontainerId);
+            wrapper.removeInitParameter(WsServlet.WEBSERVICE_CONTAINER);
+        }
+    }
+
+    public List<String> addWsContainer(String path, HttpListener httpListener, String virtualHost, String realmName, String transportGuarantee, String authMethod, ClassLoader classLoader) throws Exception {
+        if (path == null) throw new NullPointerException("contextRoot is null");
+        if (httpListener == null) throw new NullPointerException("httpListener is null");
+
+        // assure context root with a leading slash
+        if (!path.startsWith("/")) path = "/" + path;
+
+        // find the existing host (we do not auto-create hosts)
+        if (virtualHost == null) virtualHost = engine.getDefaultHost();
+        Container host = engine.findChild(virtualHost);
+        if (host == null) {
+            throw new IllegalArgumentException("Invalid virtual host '" + virtualHost + "'.  Do you have a matchiing Host entry in the server.xml?");
+        }
+
+        // build the context
+        StandardContext context = new StandardContext();
+        context.setPath(path);
+        context.setDocBase("");
+        context.setParentClassLoader(classLoader);
+        context.setDelegate(true);
+
+        // Tomcat has a stupid rule where a life cycle listener must set
+        // configured true, or it will treat it as a failed deployment
+        context.addLifecycleListener(new LifecycleListener() {
+            public void lifecycleEvent(LifecycleEvent event) {
+                if (event.getType().equals(Lifecycle.START_EVENT)) {
+                    Context context = (Context) event.getLifecycle();
+                    context.setConfigured(true);
+                }
+            }
+        });
+
+        // Configure security
+        if (authMethod != null) {
+            authMethod = authMethod.toUpperCase();
+        }
+        if (transportGuarantee != null) {
+            transportGuarantee = transportGuarantee.toUpperCase();
+        }
+        if (authMethod == null || "NONE".equals(authMethod)) {
+            // ignore none for now as the  NonLoginAuthenticator seems to be completely hosed
+        } else if ("BASIC".equals(authMethod) || "DIGEST".equals(authMethod) || "CLIENT-CERT".equals(authMethod)) {
+
+            //Setup a login configuration
+            LoginConfig loginConfig = new LoginConfig();
+            loginConfig.setAuthMethod(authMethod);
+            loginConfig.setRealmName(realmName);
+            context.setLoginConfig(loginConfig);
+
+            //Setup a default Security Constraint
+            SecurityCollection collection = new SecurityCollection();
+            collection.addMethod("GET");
+            collection.addMethod("POST");
+            collection.addPattern("/*");
+            collection.setName("default");
+            SecurityConstraint sc = new SecurityConstraint();
+            sc.addAuthRole("*");
+            sc.addCollection(collection);
+            sc.setAuthConstraint(true);
+            sc.setUserConstraint(transportGuarantee);
+            context.addConstraint(sc);
+            context.addSecurityRole("default");
+
+            //Set the proper authenticator
+            if ("BASIC".equals(authMethod)) {
+                context.addValve(new BasicAuthenticator());
+            } else if ("DIGEST".equals(authMethod)) {
+                context.addValve(new DigestAuthenticator());
+            } else if ("CLIENT-CERT".equals(authMethod)) {
+                context.addValve(new SSLAuthenticator());
+            } else if ("NONE".equals(authMethod)) {
+                context.addValve(new NonLoginAuthenticator());
+            }
+        } else {
+            throw new IllegalArgumentException("Invalid authMethod: " + authMethod);
+        }
+
+        // Mark this as a dynamic context that should not be inspected by the TomcatWebAppBuilder
+        context.getServletContext().setAttribute(IGNORE_CONTEXT, "true");
+
+        // build the servlet
+        Wrapper wrapper = context.createWrapper();
+        wrapper.setName("webservice");
+        wrapper.setServletClass(WsServlet.class.getName());
+        setWsContainer(context, wrapper, httpListener);
+        wrapper.addMapping("/*");
+
+
+        // add add servlet to context
+        context.addChild(wrapper);
+        context.addServletMapping("/*", "webservice");
+
+        // add context to host
+        host.addChild(context);
+        webserviceContexts.put(path, context);
+
+        // register wsdl locations for service-ref resolution
+        List<String> addresses = new ArrayList<String>();
+        for (Connector connector : connectors) {
+            URI address = new URI(connector.getScheme(), null, host.getName(), connector.getPort(), path, null, null);
+            addresses.add(address.toString());
+        }
+        return addresses;
+    }
+
+    public void removeWsContainer(String path) {
+        if (path == null) return;
+
+        // assure context root with a leading slash
+        if (!path.startsWith("/")) path = "/" + path;
+
+        StandardContext context = webserviceContexts.remove(path);
+        try {
+            context.stop();
+            context.destroy();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+        Host host = (Host) context.getParent();
+        host.removeChild(context);
+    }
+
+    private void setWsContainer(Context context, Wrapper wrapper, HttpListener wsContainer) {
+        // Make up an ID for the WebServiceContainer
+        // put a reference the ID in the init-params
+        // put the WebServiceContainer in the webapp context keyed by its ID
+        String webServicecontainerID = wrapper.getName() + WsServlet.WEBSERVICE_CONTAINER + wsContainer.hashCode();
+        context.getServletContext().setAttribute(webServicecontainerID, wsContainer);
+        wrapper.addInitParameter(WsServlet.WEBSERVICE_CONTAINER, webServicecontainerID);
+    }
+}

Added: openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/resources/META-INF/org.apache.openejb.tomcat/ServerClassLoader
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/resources/META-INF/org.apache.openejb.tomcat/ServerClassLoader?rev=633268&view=auto
==============================================================================
--- openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/resources/META-INF/org.apache.openejb.tomcat/ServerClassLoader (added)
+++ openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-catalina/src/main/resources/META-INF/org.apache.openejb.tomcat/ServerClassLoader Mon Mar  3 12:39:06 2008
@@ -0,0 +1 @@
+This file causes the jar containing it to be loaded into the Tomcat server classloader rather than the commom classloader
\ No newline at end of file

Modified: openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/pom.xml
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/pom.xml?rev=633268&r1=632706&r2=633268&view=diff
==============================================================================
--- openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/pom.xml (original)
+++ openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/pom.xml Mon Mar  3 12:39:06 2008
@@ -26,9 +26,10 @@
     <version>3.0-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
-  <artifactId>openejb-tomcat-naming</artifactId>
+  <artifactId>openejb-tomcat-common</artifactId>
   <packaging>jar</packaging>
-  <name>OpenEJB :: Assembly :: Tomcat :: Naming</name>
+  <name>OpenEJB :: Assembly :: Tomcat :: Common</name>
+  <description>This module contains the classes that will be added to the common class loader</description>
   <dependencies>
     <dependency>
       <groupId>org.apache.openejb</groupId>

Added: openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/AbstractObjectFactory.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/AbstractObjectFactory.java?rev=633268&view=auto
==============================================================================
--- openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/AbstractObjectFactory.java (added)
+++ openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/AbstractObjectFactory.java Mon Mar  3 12:39:06 2008
@@ -0,0 +1,77 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.openejb.tomcat.common;
+
+import org.apache.openejb.loader.SystemInstance;
+import org.apache.openejb.spi.ContainerSystem;
+import static org.apache.openejb.tomcat.common.NamingUtil.JNDI_NAME;
+import static org.apache.openejb.tomcat.common.NamingUtil.JNDI_PROVIDER_ID;
+import static org.apache.openejb.tomcat.common.NamingUtil.getProperty;
+
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.Reference;
+import javax.naming.spi.ObjectFactory;
+import java.util.Hashtable;
+
+public abstract class AbstractObjectFactory implements ObjectFactory {
+    public Object getObjectInstance(Object object, Name name, Context context, Hashtable environment) throws Exception {
+        Reference ref = (Reference) object;
+
+        // the jndi context to use for the lookup (usually null which is the default context)
+        String jndiProviderId = getProperty(ref, JNDI_PROVIDER_ID);
+
+        // the jndi name
+        String jndiName = getProperty(ref, JNDI_NAME);
+        if (jndiName == null) {
+            jndiName = buildJndiName(ref);
+        }
+
+        // look up the reference
+        Object value = lookup(jndiProviderId, jndiName);
+        return value;
+    }
+
+    protected abstract String buildJndiName(Reference reference) throws NamingException;
+
+    protected Object lookup(String jndiProviderId, String jndiName) throws NamingException {
+        Context externalContext = getContext(jndiProviderId);
+        synchronized (externalContext) {
+            /* According to the JNDI SPI specification multiple threads may not access the same JNDI
+            Context *instance* concurrently. Since we don't know the origines of the federated context we must
+            synchonrize access to it.  JNDI SPI Sepecifiation 1.2 Section 2.2
+            */
+            return externalContext.lookup(jndiName);
+        }
+    }
+
+    protected Context getContext(String jndiProviderId) throws NamingException {
+        if (jndiProviderId != null) {
+            String contextJndiName = "java:openejb/remote_jndi_contexts/" + jndiProviderId;
+            ContainerSystem containerSystem = SystemInstance.get().getComponent(ContainerSystem.class);
+            Context context = (Context) containerSystem.getJNDIContext().lookup(contextJndiName);
+            return context;
+        } else {
+            ContainerSystem containerSystem = SystemInstance.get().getComponent(ContainerSystem.class);
+            Context context = containerSystem.getJNDIContext();
+            return context;
+        }
+    }
+
+}

Added: openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/EjbFactory.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/EjbFactory.java?rev=633268&view=auto
==============================================================================
--- openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/EjbFactory.java (added)
+++ openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/EjbFactory.java Mon Mar  3 12:39:06 2008
@@ -0,0 +1,92 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.openejb.tomcat.common;
+
+import org.apache.naming.EjbRef;
+import org.apache.openejb.core.ivm.EjbObjectInputStream;
+import org.apache.openejb.core.ivm.IntraVmCopyMonitor;
+import static org.apache.openejb.tomcat.common.NamingUtil.DEPLOYMENT_ID;
+import static org.apache.openejb.tomcat.common.NamingUtil.EXTERNAL;
+import static org.apache.openejb.tomcat.common.NamingUtil.LOCAL;
+import static org.apache.openejb.tomcat.common.NamingUtil.REMOTE;
+import static org.apache.openejb.tomcat.common.NamingUtil.getProperty;
+import static org.apache.openejb.tomcat.common.NamingUtil.isPropertyTrue;
+
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.Reference;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Hashtable;
+
+public class EjbFactory extends AbstractObjectFactory {
+    public Object getObjectInstance(Object object, Name name, Context context, Hashtable environment) throws Exception {
+        // ignore non ejb-refs
+        if (!(object instanceof EjbRef)) {
+            return null;
+        }
+
+        // lookup the value
+        Object value = super.getObjectInstance(object, name, context, environment);
+
+        // if this is an external reference, copy it into the local class loader
+        if (isPropertyTrue((Reference) object, EXTERNAL)) {
+            value = copy(value);
+        }
+
+        // done
+        return value;
+    }
+
+    protected String buildJndiName(Reference reference) throws NamingException {
+        String jndiName;// get and verify deploymentId
+        String deploymentId = getProperty(reference, DEPLOYMENT_ID);
+        if (deploymentId == null) throw new NamingException("ejb-ref deploymentId is null");
+
+        // get and verify interface type
+        String interfaceType = getProperty(reference, REMOTE);
+        if (interfaceType == null) {
+            interfaceType = getProperty(reference, LOCAL);
+        }
+        if (interfaceType == null) throw new NamingException("ejb-ref interface type is null");
+
+        // build jndi name using the deploymentId and interface type
+        jndiName = "java:openejb/Deployment/" + deploymentId + "/" + interfaceType;
+        return jndiName;
+    }
+
+    private static Object copy(Object source) throws Exception {
+        IntraVmCopyMonitor.preCrossClassLoaderOperation();
+        try {
+            ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
+            ObjectOutputStream out = new ObjectOutputStream(baos);
+            out.writeObject(source);
+            out.close();
+
+            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+            ObjectInputStream in = new EjbObjectInputStream(bais);
+            Object copy = in.readObject();
+            return copy;
+        } finally {
+            IntraVmCopyMonitor.postCrossClassLoaderOperation();
+        }
+    }
+}
\ No newline at end of file

Added: openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/LegacyAnnotationProcessor.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/LegacyAnnotationProcessor.java?rev=633268&view=auto
==============================================================================
--- openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/LegacyAnnotationProcessor.java (added)
+++ openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/LegacyAnnotationProcessor.java Mon Mar  3 12:39:06 2008
@@ -0,0 +1,241 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.openejb.tomcat.common;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.annotation.Resource;
+import javax.ejb.EJB;
+import javax.naming.NamingException;
+import javax.persistence.PersistenceContext;
+import javax.persistence.PersistenceUnit;
+import javax.xml.ws.WebServiceRef;
+
+public class LegacyAnnotationProcessor {
+
+    protected javax.naming.Context context = null;
+
+    public LegacyAnnotationProcessor(javax.naming.Context context) {
+        this.context = context;
+    }
+
+
+    /**
+     * Call postConstruct method on the specified instance.
+     */
+    public void postConstruct(Object instance)
+        throws IllegalAccessException, InvocationTargetException {
+
+        Method[] methods = instance.getClass().getDeclaredMethods();
+        Method postConstruct = null;
+        for (Method method : methods) {
+            if (method.isAnnotationPresent(PostConstruct.class)) {
+                if ((postConstruct != null)
+                        || (method.getParameterTypes().length != 0)
+                        || (Modifier.isStatic(method.getModifiers()))
+                        || (method.getExceptionTypes().length > 0)
+                        || (!method.getReturnType().getName().equals("void"))) {
+                    throw new IllegalArgumentException("Invalid PostConstruct annotation");
+                }
+                postConstruct = method;
+            }
+        }
+
+        // At the end the postconstruct annotated
+        // method is invoked
+        if (postConstruct != null) {
+            boolean accessibility = postConstruct.isAccessible();
+            postConstruct.setAccessible(true);
+            postConstruct.invoke(instance);
+            postConstruct.setAccessible(accessibility);
+        }
+    }
+
+
+    /**
+     * Call preDestroy method on the specified instance.
+     */
+    public void preDestroy(Object instance)
+        throws IllegalAccessException, InvocationTargetException {
+
+        Method[] methods = instance.getClass().getDeclaredMethods();
+        Method preDestroy = null;
+        for (Method method : methods) {
+            if (method.isAnnotationPresent(PreDestroy.class)) {
+                if ((preDestroy != null)
+                        || (method.getParameterTypes().length != 0)
+                        || (Modifier.isStatic(method.getModifiers()))
+                        || (method.getExceptionTypes().length > 0)
+                        || (!method.getReturnType().getName().equals("void"))) {
+                    throw new IllegalArgumentException("Invalid PreDestroy annotation");
+                }
+                preDestroy = method;
+            }
+        }
+
+        // At the end the postconstruct annotated
+        // method is invoked
+        if (preDestroy != null) {
+            boolean accessibility = preDestroy.isAccessible();
+            preDestroy.setAccessible(true);
+            preDestroy.invoke(instance);
+            preDestroy.setAccessible(accessibility);
+        }
+
+    }
+
+
+    /**
+     * Inject resources in specified instance.
+     */
+    public void processAnnotations(Object instance)
+        throws IllegalAccessException, InvocationTargetException, NamingException {
+
+        if (context == null) {
+            // No resource injection
+            return;
+        }
+
+        // Initialize fields annotations
+        Field[] fields = instance.getClass().getDeclaredFields();
+        for (Field field : fields) {
+            if (field.isAnnotationPresent(Resource.class)) {
+                Resource annotation = field.getAnnotation(Resource.class);
+                lookupFieldResource(context, instance, field, annotation.name());
+            }
+            if (field.isAnnotationPresent(EJB.class)) {
+                EJB annotation = field.getAnnotation(EJB.class);
+                lookupFieldResource(context, instance, field, annotation.name());
+            }
+            if (field.isAnnotationPresent(WebServiceRef.class)) {
+                WebServiceRef annotation = field.getAnnotation(WebServiceRef.class);
+                lookupFieldResource(context, instance, field, annotation.name());
+            }
+            if (field.isAnnotationPresent(PersistenceContext.class)) {
+                PersistenceContext annotation = field.getAnnotation(PersistenceContext.class);
+                lookupFieldResource(context, instance, field, annotation.name());
+            }
+            if (field.isAnnotationPresent(PersistenceUnit.class)) {
+                PersistenceUnit annotation = field.getAnnotation(PersistenceUnit.class);
+                lookupFieldResource(context, instance, field, annotation.name());
+            }
+        }
+
+        // Initialize methods annotations
+        Method[] methods = instance.getClass().getDeclaredMethods();
+        for (Method method : methods) {
+            if (method.isAnnotationPresent(Resource.class)) {
+                Resource annotation = method.getAnnotation(Resource.class);
+                lookupMethodResource(context, instance, method, annotation.name());
+            }
+            if (method.isAnnotationPresent(EJB.class)) {
+                EJB annotation = method.getAnnotation(EJB.class);
+                lookupMethodResource(context, instance, method, annotation.name());
+            }
+            if (method.isAnnotationPresent(WebServiceRef.class)) {
+                WebServiceRef annotation = method.getAnnotation(WebServiceRef.class);
+                lookupMethodResource(context, instance, method, annotation.name());
+            }
+            if (method.isAnnotationPresent(PersistenceContext.class)) {
+                PersistenceContext annotation = method.getAnnotation(PersistenceContext.class);
+                lookupMethodResource(context, instance, method, annotation.name());
+            }
+            if (method.isAnnotationPresent(PersistenceUnit.class)) {
+                PersistenceUnit annotation = method.getAnnotation(PersistenceUnit.class);
+                lookupMethodResource(context, instance, method, annotation.name());
+            }
+        }
+
+    }
+
+
+    /**
+     * Inject resources in specified field.
+     */
+    protected static void lookupFieldResource(javax.naming.Context context,
+            Object instance, Field field, String name)
+        throws NamingException, IllegalAccessException {
+
+        Object lookedupResource;
+        boolean accessibility;
+
+        if ((name != null) && (name.length() > 0)) {
+            lookedupResource = context.lookup(name);
+        } else {
+            lookedupResource = context.lookup(instance.getClass().getName() + "/" + field.getName());
+        }
+
+        accessibility = field.isAccessible();
+        field.setAccessible(true);
+        field.set(instance, lookedupResource);
+        field.setAccessible(accessibility);
+    }
+
+
+    /**
+     * Inject resources in specified method.
+     */
+    protected static void lookupMethodResource(javax.naming.Context context,
+            Object instance, Method method, String name)
+        throws NamingException, IllegalAccessException, InvocationTargetException {
+
+        if (!method.getName().startsWith("set")
+                || method.getParameterTypes().length != 1
+                || !method.getReturnType().getName().equals("void")) {
+            throw new IllegalArgumentException("Invalid method resource injection annotation");
+        }
+
+        Object lookedupResource;
+        boolean accessibility;
+
+        if ((name != null) &&
+                (name.length() > 0)) {
+            lookedupResource = context.lookup(name);
+        } else {
+            lookedupResource =
+                context.lookup(instance.getClass().getName() + "/" + method.getName().substring(3));
+        }
+
+        accessibility = method.isAccessible();
+        method.setAccessible(true);
+        method.invoke(instance, lookedupResource);
+        method.setAccessible(accessibility);
+    }
+
+}

Added: openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/NamingUtil.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/NamingUtil.java?rev=633268&view=auto
==============================================================================
--- openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/NamingUtil.java (added)
+++ openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/NamingUtil.java Mon Mar  3 12:39:06 2008
@@ -0,0 +1,116 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.openejb.tomcat.common;
+
+import org.apache.naming.EjbRef;
+
+import javax.naming.RefAddr;
+import javax.naming.Reference;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class NamingUtil {
+    public static final String NAME = "name";
+    public static final String DEPLOYMENT_ID = "deploymentid";
+    public static final String EXTERNAL = "external";
+    public static final String LOCAL = "local";
+    public static final String REMOTE = EjbRef.REMOTE;
+    public static final String JNDI_NAME = "jndiname";
+    public static final String JNDI_PROVIDER_ID = "jndiproviderid";
+    public static final String UNIT = "unit";
+    public static final String EXTENDED = "extended";
+    public static final String PROPERTIES = "properties";
+    public static final String RESOURCE_ID = "resourceid";
+    public static final String COMPONENT_TYPE = "componenttype";
+    public static final String WS_ID = "wsid";
+    public static final String WS_CLASS = "wsclass";
+    public static final String WS_QNAME = "wsqname";
+    public static final String WS_PORT_QNAME = "wsportqname";
+    public static final String WSDL_URL = "wsdlurl";
+
+    private static final AtomicInteger id = new AtomicInteger(31);
+    private static final Map<String,Object> registry = new HashMap<String,Object>();
+
+    public static String getProperty(Reference ref, String name) {
+        RefAddr addr = ref.get(name);
+        if (addr == null) return null;
+        Object value = addr.getContent();
+        return (String) value;
+    }
+
+    public static boolean isPropertyTrue(Reference ref, String name) {
+        RefAddr addr = ref.get(name);
+        if (addr == null) return false;
+        Object value = addr.getContent();
+        return Boolean.parseBoolean("" + value);
+    }
+
+    public static void setStaticValue(Resource resource, Object value) {
+        setStaticValue(resource, null, value);
+    }
+
+    public static void setStaticValue(Resource resource, String name, Object value) {
+        name = name != null ? "-" + name : "";
+        String token = "" + id.incrementAndGet();
+        registry.put(token, value);
+        resource.setProperty("static-token" + name, token);
+    }
+
+    @SuppressWarnings({"unchecked"})
+    public static<T> T getStaticValue(Reference ref) {
+        return (T) getStaticValue(ref, null);
+    }
+
+    @SuppressWarnings({"unchecked"})
+    public static <T> T getStaticValue(Reference ref, String name) {
+        name = name != null ? "-" + name : "";
+        String token = getProperty(ref, "static-token" + name);
+        if (token == null) {
+            return null;
+        }
+        T object = (T) registry.get(token);
+        return object;
+    }
+
+    public static Class<?> loadClass(String className) {
+        if (className == null) return null;
+        try {
+            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+            if (classLoader != null) {
+                try {
+                    Class clazz = classLoader.loadClass(className);
+                    return clazz;
+                } catch(ClassNotFoundException e) {
+                }
+            }
+            return Class.forName(className);
+        } catch (ClassNotFoundException e) {
+            return null;
+        }
+    }
+
+    /**
+     * This interface exists because the class org.apache.catalina.deploy.ContextResource
+     * is not available in the common classloader in tomcat 55
+     */
+    public interface Resource {
+        void setProperty(String name, Object value);
+    }
+
+}

Added: openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/PersistenceContextFactory.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/PersistenceContextFactory.java?rev=633268&view=auto
==============================================================================
--- openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/PersistenceContextFactory.java (added)
+++ openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/PersistenceContextFactory.java Mon Mar  3 12:39:06 2008
@@ -0,0 +1,55 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.openejb.tomcat.common;
+
+import org.apache.naming.ResourceRef;
+import static org.apache.openejb.tomcat.common.NamingUtil.JNDI_NAME;
+import static org.apache.openejb.tomcat.common.NamingUtil.getProperty;
+import static org.apache.openejb.tomcat.common.NamingUtil.getStaticValue;
+
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.Reference;
+import java.util.Hashtable;
+
+public class PersistenceContextFactory extends AbstractObjectFactory {
+    public Object getObjectInstance(Object object, Name name, Context context, Hashtable environment) throws Exception {
+        // ignore non resource-refs
+        if (!(object instanceof ResourceRef)) {
+            return null;
+        }
+
+        Reference ref = (Reference) object;
+
+        Object value;
+        if (getProperty(ref, JNDI_NAME) != null) {
+            // lookup the value in JNDI
+            value = super.getObjectInstance(object, name, context, environment);
+        } else {
+            // value is hard hard coded in the properties
+            value = getStaticValue(ref);
+        }
+
+        return value;
+    }
+
+    protected String buildJndiName(Reference reference) throws NamingException {
+        throw new UnsupportedOperationException();
+    }
+}

Added: openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/PersistenceUnitFactory.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/PersistenceUnitFactory.java?rev=633268&view=auto
==============================================================================
--- openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/PersistenceUnitFactory.java (added)
+++ openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/PersistenceUnitFactory.java Mon Mar  3 12:39:06 2008
@@ -0,0 +1,55 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.openejb.tomcat.common;
+
+import org.apache.naming.ResourceRef;
+import static org.apache.openejb.tomcat.common.NamingUtil.JNDI_NAME;
+import static org.apache.openejb.tomcat.common.NamingUtil.getProperty;
+import static org.apache.openejb.tomcat.common.NamingUtil.getStaticValue;
+
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.Reference;
+import java.util.Hashtable;
+
+public class PersistenceUnitFactory extends AbstractObjectFactory {
+    public Object getObjectInstance(Object object, Name name, Context context, Hashtable environment) throws Exception {
+        // ignore non resource-refs
+        if (!(object instanceof ResourceRef)) {
+            return null;
+        }
+
+        Reference ref = (Reference) object;
+
+        Object value;
+        if (getProperty(ref, JNDI_NAME) != null) {
+            // lookup the value in JNDI
+            value = super.getObjectInstance(object, name, context, environment);
+        } else {
+            // value is hard hard coded in the properties
+            value = getStaticValue(ref);
+        }
+
+        return value;
+    }
+
+    protected String buildJndiName(Reference reference) throws NamingException {
+        throw new UnsupportedOperationException();
+    }
+}

Added: openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/ResourceFactory.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/ResourceFactory.java?rev=633268&view=auto
==============================================================================
--- openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/ResourceFactory.java (added)
+++ openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/ResourceFactory.java Mon Mar  3 12:39:06 2008
@@ -0,0 +1,54 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.openejb.tomcat.common;
+
+import static org.apache.openejb.tomcat.common.NamingUtil.NAME;
+import static org.apache.openejb.tomcat.common.NamingUtil.RESOURCE_ID;
+import static org.apache.openejb.tomcat.common.NamingUtil.getProperty;
+
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.Reference;
+import java.net.URL;
+import java.util.Hashtable;
+
+public class ResourceFactory extends AbstractObjectFactory {
+    public Object getObjectInstance(Object object, Name name, Context context, Hashtable environment) throws Exception {
+        Reference reference = ((Reference) object);
+        if (reference.getClassName().equals("java.net.URL")) {
+            String resourceId = getProperty(reference, RESOURCE_ID);
+            return new URL(resourceId);
+        }
+        return super.getObjectInstance(object, name, context, environment);
+    }
+
+    protected String buildJndiName(Reference reference) throws NamingException {
+        // get and verify interface type
+        String resourceId = getProperty(reference, RESOURCE_ID);
+        if (resourceId == null) {
+            resourceId = getProperty(reference, NAME);
+        }
+        if (resourceId == null) throw new NamingException("Resource reference id is null");
+
+        // build jndi name using the deploymentId and interface type
+        String jndiName = "java:openejb/Resource/" + resourceId;
+        return jndiName;
+    }
+
+}

Added: openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/ServerServlet.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/ServerServlet.java?rev=633268&view=auto
==============================================================================
--- openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/ServerServlet.java (added)
+++ openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/ServerServlet.java Mon Mar  3 12:39:06 2008
@@ -0,0 +1,49 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.openejb.tomcat.common;
+
+import org.apache.openejb.loader.SystemInstance;
+import org.apache.openejb.server.ServiceException;
+import org.apache.openejb.server.ejbd.EjbServer;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletInputStream;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+public class ServerServlet extends HttpServlet {
+    private EjbServer ejbServer;
+
+    public void init(ServletConfig config) {
+        ejbServer = SystemInstance.get().getComponent(EjbServer.class);
+    }
+
+    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+        ServletInputStream in = request.getInputStream();
+        ServletOutputStream out = response.getOutputStream();
+        try {
+            ejbServer.service(in, out);
+        } catch (ServiceException e) {
+            throw new ServletException("ServerService error: " + ejbServer.getClass().getName() + " -- " + e.getMessage(), e);
+        }
+    }
+}

Added: openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/SystemComponentFactory.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/SystemComponentFactory.java?rev=633268&view=auto
==============================================================================
--- openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/SystemComponentFactory.java (added)
+++ openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-common/src/main/java/org/apache/openejb/tomcat/common/SystemComponentFactory.java Mon Mar  3 12:39:06 2008
@@ -0,0 +1,44 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.openejb.tomcat.common;
+
+import org.apache.openejb.loader.SystemInstance;
+import static org.apache.openejb.tomcat.common.NamingUtil.COMPONENT_TYPE;
+import static org.apache.openejb.tomcat.common.NamingUtil.getProperty;
+import static org.apache.openejb.tomcat.common.NamingUtil.loadClass;
+
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.Reference;
+import javax.naming.spi.ObjectFactory;
+import java.util.Hashtable;
+
+public class SystemComponentFactory implements ObjectFactory {
+    public Object getObjectInstance(Object object, Name name, Context context, Hashtable environment) throws Exception {
+        Reference ref = (Reference) object;
+
+        // load the component type class
+        String className = getProperty(ref, COMPONENT_TYPE);
+        Class<?> clazz = loadClass(className);
+        if (clazz == null) return null;
+
+        // lookup the value
+        Object value = SystemInstance.get().getComponent(clazz);
+        return value;
+    }
+}