/*
 * 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.tomee.catalina;

import org.apache.catalina.Cluster;
import org.apache.catalina.Container;
import org.apache.catalina.Engine;
import org.apache.catalina.Host;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleListener;
import org.apache.catalina.LifecycleState;
import org.apache.catalina.Loader;
import org.apache.catalina.Manager;
import org.apache.catalina.Pipeline;
import org.apache.catalina.Realm;
import org.apache.catalina.Service;
import org.apache.catalina.UserDatabase;
import org.apache.catalina.Valve;
import org.apache.catalina.WebResource;
import org.apache.catalina.WebResourceRoot;
import org.apache.catalina.WebResourceSet;
import org.apache.catalina.Wrapper;
import org.apache.catalina.connector.Request;
import org.apache.catalina.core.ContainerBase;
import org.apache.catalina.core.NamingContextListener;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.core.StandardHost;
import org.apache.catalina.core.StandardServer;
import org.apache.catalina.core.StandardWrapper;
import org.apache.catalina.deploy.NamingResourcesImpl;
import org.apache.catalina.ha.CatalinaCluster;
import org.apache.catalina.ha.tcp.SimpleTcpCluster;
import org.apache.catalina.loader.WebappLoader;
import org.apache.catalina.session.StandardManager;
import org.apache.catalina.startup.Constants;
import org.apache.catalina.startup.ContextConfig;
import org.apache.catalina.startup.HostConfig;
import org.apache.catalina.startup.OpenEJBContextConfig;
import org.apache.catalina.users.MemoryUserDatabase;
import org.apache.catalina.webresources.DirResourceSet;
import org.apache.naming.ContextAccessController;
import org.apache.naming.ContextBindings;
import org.apache.naming.ResourceEnvRef;
import org.apache.naming.ResourceRef;
import org.apache.openejb.AppContext;
import org.apache.openejb.BeanContext;
import org.apache.openejb.BeanType;
import org.apache.openejb.ClassLoaderUtil;
import org.apache.openejb.Injection;
import org.apache.openejb.OpenEJBException;
import org.apache.openejb.OpenEJBRuntimeException;
import org.apache.openejb.assembler.DeployerEjb;
import org.apache.openejb.assembler.classic.AppInfo;
import org.apache.openejb.assembler.classic.Assembler;
import org.apache.openejb.assembler.classic.ClassListInfo;
import org.apache.openejb.assembler.classic.ConnectorInfo;
import org.apache.openejb.assembler.classic.DeploymentExceptionManager;
import org.apache.openejb.assembler.classic.EjbJarInfo;
import org.apache.openejb.assembler.classic.InjectionBuilder;
import org.apache.openejb.assembler.classic.JaccPermissionsBuilder;
import org.apache.openejb.assembler.classic.JndiEncBuilder;
import org.apache.openejb.assembler.classic.OpenEjbConfiguration;
import org.apache.openejb.assembler.classic.OpenEjbConfigurationFactory;
import org.apache.openejb.assembler.classic.PersistenceUnitInfo;
import org.apache.openejb.assembler.classic.PolicyContext;
import org.apache.openejb.assembler.classic.ReloadableEntityManagerFactory;
import org.apache.openejb.assembler.classic.ResourceInfo;
import org.apache.openejb.assembler.classic.ServletInfo;
import org.apache.openejb.assembler.classic.WebAppBuilder;
import org.apache.openejb.assembler.classic.WebAppInfo;
import org.apache.openejb.assembler.classic.event.NewEjbAvailableAfterApplicationCreated;
import org.apache.openejb.cdi.CdiAppContextsService;
import org.apache.openejb.cdi.CdiBuilder;
import org.apache.openejb.cdi.OpenEJBLifecycle;
import org.apache.openejb.cdi.Proxys;
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.TldScanner;
import org.apache.openejb.config.WebModule;
import org.apache.openejb.config.sys.Resource;
import org.apache.openejb.core.CoreContainerSystem;
import org.apache.openejb.core.ParentClassLoaderFinder;
import org.apache.openejb.core.WebContext;
import org.apache.openejb.core.ivm.IntraVmProxy;
import org.apache.openejb.core.ivm.naming.SystemComponentReference;
import org.apache.openejb.jee.EnvEntry;
import org.apache.openejb.jee.WebApp;
import org.apache.openejb.loader.Files;
import org.apache.openejb.loader.SystemInstance;
import org.apache.openejb.server.httpd.BeginWebBeansListener;
import org.apache.openejb.server.httpd.EndWebBeansListener;
import org.apache.openejb.server.httpd.HttpSession;
import org.apache.openejb.spi.ContainerSystem;
import org.apache.openejb.util.LogCategory;
import org.apache.openejb.util.Logger;
import org.apache.openejb.util.URLs;
import org.apache.openejb.util.proxy.LocalBeanProxyFactory;
import org.apache.openejb.util.reflection.Reflections;
import org.apache.tomcat.InstanceManager;
import org.apache.tomcat.JarScanFilter;
import org.apache.tomcat.util.descriptor.web.ApplicationParameter;
import org.apache.tomcat.util.descriptor.web.ContextEnvironment;
import org.apache.tomcat.util.descriptor.web.ContextResource;
import org.apache.tomcat.util.descriptor.web.ContextResourceLink;
import org.apache.tomcat.util.descriptor.web.ContextTransaction;
import org.apache.tomcat.util.descriptor.web.FilterDef;
import org.apache.tomcat.util.descriptor.web.FilterMap;
import org.apache.tomcat.util.descriptor.web.ResourceBase;
import org.apache.tomcat.util.http.CookieProcessor;
import org.apache.tomcat.util.scan.StandardJarScanFilter;
import org.apache.tomee.catalina.cdi.ServletContextHandler;
import org.apache.tomee.catalina.cdi.WebBeansThreadBindingListener;
import org.apache.tomee.catalina.cluster.ClusterObserver;
import org.apache.tomee.catalina.cluster.TomEEClusterListener;
import org.apache.tomee.catalina.environment.Hosts;
import org.apache.tomee.catalina.event.AfterApplicationCreated;
import org.apache.tomee.catalina.routing.RouterValve;
import org.apache.tomee.catalina.security.TomcatSecurityConstaintsToJaccPermissionsTransformer;
import org.apache.tomee.common.NamingUtil;
import org.apache.tomee.common.UserTransactionFactory;
import org.apache.tomee.config.TomEESystemConfig;
import org.apache.tomee.loader.TomcatHelper;
import org.apache.webbeans.config.WebBeansContext;
import org.apache.webbeans.spi.ContextsService;

import javax.ejb.spi.HandleDelegate;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NameNotFoundException;
import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.StringRefAddr;
import javax.servlet.ServletContext;
import javax.servlet.SessionTrackingMode;
import javax.servlet.http.HttpServletRequest;
import javax.sql.DataSource;
import javax.transaction.TransactionManager;
import javax.transaction.TransactionSynchronizationRegistry;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import static java.util.Arrays.asList;
import static org.apache.tomee.catalina.Contexts.warPath;

/**
 * Web application builder.
 *
 * @version $Rev$ $Date$
 */
public class TomcatWebAppBuilder implements WebAppBuilder, ContextListener, ParentClassLoaderFinder {

    public static final String OPENEJB_CROSSCONTEXT_PROPERTY = "openejb.crosscontext";
    public static final String OPENEJB_SESSION_MANAGER_PROPERTY = "openejb.session.manager";
    public static final String OPENEJB_JSESSION_ID_SUPPORT = "openejb.jsessionid-support";
    public static final String OPENEJB_MYFACES_DISABLE_DEFAULT_VALUES = "openejb.myfaces.disable-default-values";

    /**
     * Flag for ignore context
     */
    public static final String IGNORE_CONTEXT = TomcatWebAppBuilder.class.getName() + ".IGNORE";
    /**
     * Logger instance
     */
    private static final Logger LOGGER = Logger.getInstance(LogCategory.OPENEJB.createChild("tomcat"), "org.apache.openejb.util.resources");

    public static final String DEFAULT_J2EE_SERVER = "Apache TomEE";
    public static final String OPENEJB_WEBAPP_MODULE_ID = "openejb.webapp.moduleId";

    private static final boolean FORCE_RELOADABLE = SystemInstance.get().getOptions().get("tomee.force-reloadable", false);
    private static final boolean SKIP_TLD = SystemInstance.get().getOptions().get("tomee.skip-tld", false);

    private static final Method GET_NAMING_CONTEXT_NAME; // it just sucks but that's private

    static {
        try {
            GET_NAMING_CONTEXT_NAME = StandardContext.class.getDeclaredMethod("getNamingContextName");
            GET_NAMING_CONTEXT_NAME.setAccessible(true);
        } catch (final NoSuchMethodException e) {
            throw new OpenEJBRuntimeException("can't find method getNamingContextName", e);
        }
    }

    private final Map<String, Realm> realms = new ConcurrentHashMap<>();

    private final Map<ClassLoader, InstanceManager> instanceManagers = new ConcurrentHashMap<>();

    /**
     * Context information for web applications
     */
    private final Map<String, ContextInfo> infos = new HashMap<>();
    /**
     * Global listener for Tomcat fired events.
     */
    private final GlobalListenerSupport globalListenerSupport;
    /**
     * OpenEJB configuration factory instance
     */
    private final ConfigurationFactory configurationFactory;
    /**
     * Tomcat host config elements
     */
    //Key is the host name
    private final Map<String, HostConfig> deployers = new TreeMap<>();
    private final Hosts hosts;
    /**
     * Deployed web applications
     */
    // todo merge this map witth the infos map above
    private final Map<String, DeployedApplication> deployedApps = new TreeMap<>();
    /**
     * OpenEJB deployment loader instance
     */
    private final DeploymentLoader deploymentLoader;
    /**
     * OpenEJB assembler instance
     * TODO can we use the SPI interface instead?
     */
    private Assembler assembler;
    /**
     * OpenEJB container system
     * TODO can we use the SPI interface instead?
     */
    private CoreContainerSystem containerSystem;

    private final Map<ClassLoader, Map<String, Set<String>>> jsfClasses = new HashMap<>();

    private Class<?> sessionManagerClass;

    private final Set<CatalinaCluster> clusters = new HashSet<>();

    private ClassLoader parentClassLoader;
    private boolean initJEEInfo = true;
    private final ServletContextHandler servletContextHandler;
    private final boolean noHostCheck;

    /**
     * Creates a new web application builder
     * instance.
     */
    public TomcatWebAppBuilder() {
        SystemInstance.get().setComponent(WebAppBuilder.class, this);
        SystemInstance.get().setComponent(TomcatWebAppBuilder.class, this);
        initJEEInfo = "true".equalsIgnoreCase(SystemInstance.get().getProperty(TomEESystemConfig.TOMEE_INIT_J2EE_INFO, "true"));

        // TODO: re-write this bit, so this becomes part of the listener, and we register this with the mbean server.

        final StandardServer standardServer = TomcatHelper.getServer();
        globalListenerSupport = new GlobalListenerSupport(standardServer, this);

        //Getting host config listeners
        hosts = new Hosts();
        SystemInstance.get().setComponent(Hosts.class, hosts);
        final ClassLoader tccl = Thread.currentThread().getContextClassLoader();
        for (final Service service : standardServer.findServices()) {
            if (service.getContainer() instanceof Engine) {
                final Engine engine = service.getContainer();

                // add the global router if relevant
                final URL globalRouterConf = RouterValve.serverRouterConfigurationURL();
                if (globalRouterConf != null) {
                    final RouterValve routerValve = new RouterValve();
                    routerValve.setConfigurationPath(globalRouterConf);
                    engine.getPipeline().addValve(routerValve);
                }

                parentClassLoader = engine.getParentClassLoader();
                if (parentClassLoader == ClassLoader.getSystemClassLoader() && parentClassLoader != tccl) {
                    parentClassLoader = tccl;
                    engine.setParentClassLoader(tccl);
                } // else assume tomcat was setup to force a classloader and then respect it

                manageCluster(engine.getCluster());
                hosts.setDefault(engine.getDefaultHost());
                addTomEERealm(engine);

                for (final Container engineChild : engine.findChildren()) {
                    if (engineChild instanceof StandardHost) {
                        final StandardHost host = (StandardHost) engineChild;
                        manageCluster(host.getCluster());
                        addTomEERealm(host);
                        host.getPipeline().addValve(new OpenEJBSecurityListener.RequestCapturer());
                        hosts.add(host);
                        for (final LifecycleListener listener : host.findLifecycleListeners()) {
                            if (listener instanceof HostConfig) {
                                final HostConfig hostConfig = (HostConfig) listener;
                                deployers.put(host.getName(), hostConfig);
                            }
                        }
                    }
                }
            }
        }

        SystemInstance.get().addObserver(new ClusterObserver(clusters));

        final OpenEjbConfigurationFactory component = SystemInstance.get().getComponent(OpenEjbConfigurationFactory.class);
        ConfigurationFactory configurationFactory = ConfigurationFactory.class.isInstance(component) ?
                ConfigurationFactory.class.cast(component) : SystemInstance.get().getComponent(ConfigurationFactory.class);
        if (configurationFactory == null) {
            configurationFactory = new ConfigurationFactory();
        }
        this.configurationFactory = configurationFactory;
        deploymentLoader = new DeploymentLoader();

        servletContextHandler = new ServletContextHandler();
        setComponentsUsedByCDI();

        try { // before tomcat was using ServiceLoader or manually instantiation, now it uses SL for itself so we can be in conflict
            WebSockets.setConfigurator();
        } catch (final Throwable th) {
            // no-op: can be another API impl, normally we are ok, this is really just a safe belt
        }

        noHostCheck = !Boolean.parseBoolean(SystemInstance.get().getProperty("tomee.host.check", "true"));
    }

    private void setComponentsUsedByCDI() {
        final SystemInstance systemInstance = SystemInstance.get();
        if (systemInstance.getComponent(HttpServletRequest.class) == null) {
            systemInstance.setComponent(HttpServletRequest.class, Proxys.threadLocalProxy(HttpServletRequest.class, OpenEJBSecurityListener.requests, null));
        }
        if (systemInstance.getComponent(HttpSession.class) == null) {
            systemInstance.setComponent(javax.servlet.http.HttpSession.class, Proxys.threadLocalRequestSessionProxy(OpenEJBSecurityListener.requests, null));
        }
        if (systemInstance.getComponent(ServletContext.class) == null) {
            systemInstance.setComponent(ServletContext.class, Proxys.handlerProxy(servletContextHandler, ServletContext.class, CdiAppContextsService.FiredManually.class));
        }
    }

    private void manageCluster(final Cluster cluster) {
        if (cluster == null || cluster instanceof SimpleTomEETcpCluster) {
            return;
        }

        Cluster current = cluster;
        if (cluster instanceof SimpleTcpCluster) {
            final Container container = cluster.getContainer();
            current = new SimpleTomEETcpCluster((SimpleTcpCluster) cluster);
            container.setCluster(current);
        }

        if (current instanceof CatalinaCluster) {
            final CatalinaCluster haCluster = (CatalinaCluster) current;
            TomEEClusterListener listener = SystemInstance.get().getComponent(TomEEClusterListener.class);
            if (listener == null) {
                listener = new TomEEClusterListener();
                SystemInstance.get().setComponent(TomEEClusterListener.class, listener);
            }
            haCluster.addClusterListener(listener); // better to be a singleton
            clusters.add(haCluster);
        }
    }

    private void addTomEERealm(final Engine engine) {
        final Realm realm = engine.getRealm();
        if (realm != null && !(realm instanceof TomEERealm) && (engine.getParent() == null || (!realm.equals(engine.getParent().getRealm())))) {
            final Realm tomeeRealm = tomeeRealm(realm);
            engine.setRealm(tomeeRealm);
            if (LifecycleState.STARTING_PREP.equals(engine.getState())) {
                try {
                    Lifecycle.class.cast(tomeeRealm).start();
                } catch (final LifecycleException e) {
                    throw new IllegalStateException(e);
                }
            }
        }
    }

    private void addTomEERealm(final Host host) {
        final Realm realm = host.getRealm();
        if (realm != null && !(realm instanceof TomEERealm) && (host.getParent() == null || (!realm.equals(host.getParent().getRealm())))) {
            host.setRealm(tomeeRealm(realm));
        }
    }

    protected Realm tomeeRealm(final Realm realm) {
        final TomEERealm trealm = new TomEERealm();
        trealm.setRealmPath("/tomee");
        trealm.addRealm(realm);
        return trealm;
    }

    /**
     * Start operation.
     */
    public void start() {
        globalListenerSupport.start();
    }

    /**
     * Stop operation.
     */
    public void stop() {
        globalListenerSupport.stop();
    }

    @Override
    public void start(final StandardServer server) {
        if (SystemInstance.get().isDefaultProfile()) { // add user tomee is no user are specified
            try {
                final NamingResourcesImpl resources = server.getGlobalNamingResources();
                final ContextResource userDataBaseResource = resources.findResource("UserDatabase");
                final UserDatabase db = (UserDatabase) server.getGlobalNamingContext().lookup(userDataBaseResource.getName());
                if (!db.getUsers().hasNext() && db instanceof MemoryUserDatabase) {
                    final MemoryUserDatabase mudb = (MemoryUserDatabase) db;
                    final boolean oldRo = mudb.getReadonly();
                    try {
                        ((MemoryUserDatabase) db).setReadonly(false);

                        db.createRole("tomee-admin", "tomee admin role");
                        db.createUser("tomee", "tomee", "TomEE");
                        db.findUser("tomee").addRole(db.findRole("tomee-admin"));
                    } finally {
                        mudb.setReadonly(oldRo);
                    }
                }
            } catch (final Throwable t) {
                // no-op
            }
        }
    }

    //
    // OpenEJB WebAppBuilder
    //

    /**
     * {@inheritDoc}
     */
    @Override
    public void deployWebApps(final AppInfo appInfo, final ClassLoader classLoader) throws Exception {
        try {
            for (final WebAppInfo webApp : appInfo.webApps) {
                // look for context.xml
                final File war = new File(webApp.path);
                URL contextXmlUrl = null;
                if (war.isDirectory()) {
                    final File cXml = new File(war, Constants.ApplicationContextXml).getAbsoluteFile();
                    if (cXml.exists()) {
                        contextXmlUrl = cXml.toURI().toURL();
                        LOGGER.info("using context file " + cXml.getAbsolutePath());
                    }
                } else { // war
                    try (final JarFile warAsJar = new JarFile(war)) {
                        final JarEntry entry = warAsJar.getJarEntry(Constants.ApplicationContextXml);
                        if (entry != null) {
                            contextXmlUrl = new URL("jar:" + war.getAbsoluteFile().toURI().toURL().toExternalForm() + "!/" + Constants.ApplicationContextXml);
                        }
                    }
                }

                if (isAlreadyDeployed(appInfo, webApp)) {
                    continue;
                }

                StandardContext standardContext;
                {
                    final ClassLoader containerLoader = Helper.get();
                    final Host host = hosts.getDefault();
                    if (StandardHost.class.isInstance(host) && !StandardContext.class.getName().equals(StandardHost.class.cast(host).getContextClass())) {
                        try {
                            standardContext = StandardContext.class.cast(containerLoader.loadClass(StandardHost.class.cast(host).getContextClass()).newInstance());
                        } catch (final Throwable th) {
                            LOGGER.warning("Can't use context class specified, using default StandardContext", th);
                            standardContext = new StandardContext();
                        }
                    } else {
                        standardContext = new StandardContext();
                    }
                    // should be optional but in maven parent is app loader and not maven loader which is the real parent
                    final ClassLoader currentParent = standardContext.getParentClassLoader();
                    if (currentParent == null || isParent(currentParent, containerLoader)) {
                        standardContext.setParentClassLoader(containerLoader);
                    }
                }
                standardContext.setUnpackWAR(!"false".equalsIgnoreCase(appInfo.properties.getProperty("tomcat.unpackWar")));
                if (contextXmlUrl != null) {
                    standardContext.setConfigFile(contextXmlUrl);
                }

                // override path if needed - hack at this moment just to pass the TCK
                // Tomcat should definitely implement it, but community does not seem to like the feature and therefore
                // willing to implement it.
                // default context path must start with / but not end with slash
                try {
                    if (webApp.defaultContextPath != null && webApp.defaultContextPath.matches("^/\\w*[^/]$")) {
                        standardContext.setPath(webApp.defaultContextPath);
                    }

                } catch (final Exception e) {
                    // don't fail because it's a hack, just output the exception
                    e.printStackTrace();
                }

                if (standardContext.getPath() != null) {
                    webApp.contextRoot = standardContext.getPath();
                }
                if (webApp.contextRoot.startsWith("/") || webApp.contextRoot.startsWith(File.separator)) {
                    webApp.contextRoot = webApp.contextRoot.substring(1);
                }
                if (webApp.contextRoot.startsWith(File.separator)) {
                    webApp.contextRoot = webApp.contextRoot.replaceFirst(File.separator, "");
                }

                // /!\ take care, StandardContext default host = "_" and not null or localhost
                final String hostname = Contexts.getHostname(standardContext);
                if (hostname != null && !"_".equals(hostname)) {
                    webApp.host = hostname;
                }

                final ApplicationParameter appParam = new ApplicationParameter();
                appParam.setName(OPENEJB_WEBAPP_MODULE_ID);
                appParam.setValue(webApp.moduleId);
                standardContext.addApplicationParameter(appParam);

                if (!isAlreadyDeployed(appInfo, webApp)) {
                    if (standardContext.getPath() == null) {
                        if (webApp.contextRoot != null && webApp.contextRoot.startsWith("/")) {
                            standardContext.setPath(webApp.contextRoot);
                        } else if (isRoot(webApp.contextRoot)) {
                            standardContext.setPath("");
                        } else {
                            standardContext.setPath("/" + webApp.contextRoot);
                        }
                    }
                    if (standardContext.getDocBase() == null) {
                        standardContext.setDocBase(webApp.path);
                    }
                    String docBase = standardContext.getDocBase();
                    File docBaseFile = new File(docBase);
                    if (docBase != null && docBaseFile.isFile() && docBase.endsWith(".war")) {
                        DeploymentLoader.unpack(docBaseFile);
                        if (standardContext.getPath().endsWith(".war")) {
                            standardContext.setPath(removeFirstSlashAndWar("/" + standardContext.getPath()));
                            standardContext.setName(standardContext.getPath());
                            webApp.contextRoot = standardContext.getPath();
                        }
                        standardContext.setDocBase(docBase.substring(0, docBase.length() - 4));
                    }
                    if (isRoot(standardContext.getName())) {
                        standardContext.setName("");
                        webApp.contextRoot = "";
                    }

                    if (isAlreadyDeployed(appInfo, webApp)) { // possible because of the previous renaming
                        continue;
                    }

                    // add classloader which is an URLClassLoader created by openejb
                    // {@see Assembler}
                    //
                    // we add it as parent classloader since we scanned classes with this classloader
                    // that's why we force delegate to true.
                    //
                    // However since this classloader and the webappclassloader will have a lot
                    // of common classes/resources we have to avoid duplicated resources
                    // so we contribute a custom loader.
                    //
                    // Note: the line standardContext.getLoader().setDelegate(true);
                    // could be hardcoded in the custom loader
                    // but here we have all the classloading logic
                    if (classLoader != null) {
                        standardContext.setParentClassLoader(classLoader);
                        standardContext.setDelegate(true);
                    }

                    String host = webApp.host;
                    if (host == null) {
                        host = hosts.getDefaultHost();
                        LOGGER.info("using default host: " + host);
                    }

                    if (classLoader != null) {
                        appInfo.autoDeploy = false;
                        deployWar(standardContext, host, appInfo);
                    } else { // force a normal deployment with lazy building of AppInfo
                        deployWar(standardContext, host, null);
                    }

                    // TODO should we copy the information in the appInfo using the jee object tree or add more to the info tree
                    // this might then move to the assembler after webapp is deployed so we can read information from info tree
                    // and build up all policy context from there instead of from Tomcat internal objects
                    final TomcatSecurityConstaintsToJaccPermissionsTransformer transformer =
                        new TomcatSecurityConstaintsToJaccPermissionsTransformer(standardContext);
                    final PolicyContext policyContext = transformer.createResourceAndDataPermissions();

                    final JaccPermissionsBuilder jaccPermissionsBuilder = new JaccPermissionsBuilder();
                    jaccPermissionsBuilder.install(policyContext);

                }
            }
        } finally { // cleanup temp var passing
            for (final WebAppInfo webApp : appInfo.webApps) {
                appInfo.properties.remove(webApp);
            }
        }
    }

    private boolean isAlreadyDeployed(final AppInfo appInfo, final WebAppInfo webApp) {
        final String version = appVersion(appInfo);
        final ContextInfo contextInfo = getContextInfo(webApp.host, webApp.contextRoot, version);
        if (contextInfo != null && contextInfo.standardContext != null && contextInfo.standardContext.getState() == LifecycleState.FAILED) {
            synchronized (infos) {
                infos.remove(getId(webApp.host, webApp.contextRoot, version));
            }
            return false;
        }
        return contextInfo != null;
    }

    private static boolean isParent(final ClassLoader parent, final ClassLoader child) {
        ClassLoader current = child;
        while (current != null) {
            if (current == parent) {
                return true;
            }
            current = current.getParent();
        }
        return child.getParent() == null && child != ClassLoader.getSystemClassLoader(); // maven ClassRealm classloader...yeah that's not awesome
    }

    private static boolean isRoot(final String name) {
        return "/ROOT".equals(name) || "ROOT".equals(name) || name == null || name.isEmpty() || "ROOT.war".equals(name);
    }

    public void deployWar(final StandardContext standardContext, final String host, final AppInfo info) {
        // TODO: instead of storing deployers, we could just lookup the right hostconfig for the server.
        final HostConfig deployer = deployers.get(host);
        if (isReady(deployer)) { // if not ready using directly host to avoid a NPE
            if (info != null) {
                final ContextInfo contextInfo = addContextInfo(host, standardContext);
                contextInfo.appInfo = info;
                contextInfo.deployer = deployer;
                contextInfo.module = extractModule(standardContext, info);
            }

            deployer.manageApp(standardContext);
        } else {
            final Host theHost = hosts.get(host);
            if (theHost != null) {
                if (info != null) {
                    final ContextInfo contextInfo = addContextInfo(host, standardContext);
                    contextInfo.appInfo = info;
                    contextInfo.host = theHost;
                    contextInfo.module = extractModule(standardContext, info);
                }

                theHost.addChild(standardContext);
            }
        }
    }

    private EjbModule extractModule(final StandardContext standardContext, final AppInfo appInfo) {
        for (final WebAppInfo app : appInfo.webApps) {
            if (app.path != null && warPath(standardContext).equals(rootPath(new File(app.path)))) {
                // see org.apache.openejb.config.ConfigurationFactory.configureApplication(java.io.File)
                return EjbModule.class.cast(appInfo.properties.remove(app));
            }
        }
        return null;
    }

    public synchronized ContextInfo standaAloneWebAppInfo(final File file) {
        for (final ContextInfo info : infos.values()) {
            if (info.appInfo != null && info.appInfo.webAppAlone
                    && ((file.equals(new File(info.appInfo.path)) || file.equals(new File(info.appInfo.path + ".war"))))) {
                return info;
            }
            if (info.standardContext != null && (file.equals(new File(info.standardContext.getDocBase())) || file.equals(new File(info.standardContext.getDocBase() + ".war")))) {
                return info;
            }
        }

        // still not found - trying another algorithm - weird but it seems to happen
        final String path = file.getAbsolutePath();
        for (final ContextInfo info : infos.values()) {
            if (info.appInfo != null && info.appInfo.webAppAlone
                    && (info.appInfo.path.endsWith(path) || (info.appInfo.path + ".war").endsWith(path))) {
                return info;
            }
        }

        return null;
    }

    public synchronized Collection<String> availableApps() {
        final Collection<String> apps = new ArrayList<>();
        for (final ContextInfo info : infos.values()) {
            if (info.appInfo != null) {
                apps.add(info.appInfo.path);
            } else if (info.standardContext != null) {
                apps.add("[not deployed] " + info.standardContext.getName());
            }
        }
        return apps;
    }

    // TODO: find something more sexy
    private static final AtomicReference<Field> HOST_CONFIG_HOST = new AtomicReference<>(null);

    static {
        try { // do it only once
            HOST_CONFIG_HOST.set(HostConfig.class.getDeclaredField("host"));
        } catch (final NoSuchFieldException e) {
            // no-op
        }
    }

    private static boolean isReady(final HostConfig deployer) {
        if (deployer != null && HOST_CONFIG_HOST.get() != null) {
            try {
                return HOST_CONFIG_HOST.get().get(deployer) != null;
            } catch (final Exception e) {
                // no-op
            }
        }
        return false;
    }

    /**
     * just to avoid a lot of log lines which are often useless.
     *
     * @param context the servlet context to init.
     */
    private static void addMyFacesDefaultParameters(final ClassLoader classLoader, final ServletContext context) {
        if (!SystemInstance.get().getOptions().get(OPENEJB_MYFACES_DISABLE_DEFAULT_VALUES, false)) {
            if (classLoader != null) {
                try { // if myfaces is not here we doesn't need any trick
                    classLoader.loadClass("org.apache.myfaces.shared.config.MyfacesConfig");
                } catch (final ClassNotFoundException cnfe) {
                    return;
                }
            }

            setInitParameter(context, "org.apache.myfaces.LOG_WEB_CONTEXT_PARAMS", "false");
            setInitParameter(context, "org.apache.myfaces.EL_RESOLVER_COMPARATOR", "org.apache.myfaces.el.unified.OpenWebBeansELResolverComparator");
            setInitParameter(context, "org.apache.myfaces.EXPRESSION_FACTORY", "org.apache.el.ExpressionFactoryImpl");
        }
    }

    private static void setInitParameter(final ServletContext context, final String key, final String value) {
        if (context.getInitParameter(key) == null) {
            context.setInitParameter(key, value);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void undeployWebApps(final AppInfo appInfo) throws Exception {
        final String version = appVersion(appInfo);
        for (final WebAppInfo webApp : appInfo.webApps) {
            final ContextInfo contextInfo = getContextInfo(webApp.host, webApp.contextRoot, version);

            if (contextInfo != null) {
                final StandardContext standardContext = contextInfo.standardContext;

                if (!appInfo.webAppAlone || !appInfo.properties.containsKey("tomee.destroying")) {
                    undeploy(standardContext, contextInfo);
                    final File extracted = Contexts.warPath(standardContext);
                    if (isExtracted(extracted)) {
                        deleteDir(extracted);
                    }
                    removeContextInfo(standardContext);
                }
            }
        }
    }

    @SuppressWarnings("PMD.UnusedFormalParameter")
    private boolean isExtracted(final File extracted) {
        // TODO: do we want to delete it?
        return false;
    }

    /**
     * Deletes given directory.
     *
     * @param dir directory
     */
    private void deleteDir(final File dir) {
        if (dir == null) {
            return;
        }
        if (dir.isFile()) {
            return;
        }
        final File[] files = dir.listFiles();
        if (files != null) {
            for (final File file : files) {
                if (file.isDirectory()) {
                    deleteDir(file);
                } else {
                    if (!file.delete()) {
                        file.deleteOnExit();
                    }
                }
            }
        }
        if (!dir.delete()) {
            dir.deleteOnExit();
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void init(final StandardContext standardContext) {
        if (isIgnored(standardContext)) {
            return;
        }

        // just adding a carriage return to get logs more readable
        LOGGER.info("------------------------- "
                + Contexts.getHostname(standardContext).replace("_", hosts.getDefaultHost()) + " -> "
                + finalName(standardContext.getPath()));

        if (FORCE_RELOADABLE) {
            final ContextInfo ctxInfo = getContextInfo(standardContext);
            if (ctxInfo == null || (ctxInfo.appInfo != null && ctxInfo.appInfo.webAppAlone)) { // don't do it for ears
                standardContext.setReloadable(true);
            }
        }
        if (SKIP_TLD) {
            if (standardContext.getJarScanner() != null && standardContext.getJarScanner().getJarScanFilter() != null) {
                final JarScanFilter jarScanFilter = standardContext.getJarScanner().getJarScanFilter();
                if (StandardJarScanFilter.class.isInstance(jarScanFilter)) {
                    StandardJarScanFilter.class.cast(jarScanFilter).setDefaultTldScan(false);
                }
            }
        }

        final String name = standardContext.getName();

        initJ2EEInfo(standardContext);

        File warFile = Contexts.warPath(standardContext);
        if (!warFile.exists()) {
            return;
        }

        if (!warFile.isDirectory()) {
            try {
                warFile = DeploymentLoader.unpack(warFile);
            } catch (final OpenEJBException e) {
                LOGGER.error("can't unpack '" + warFile.getAbsolutePath() + "'");
            }
        }

        standardContext.setCrossContext(SystemInstance.get().getOptions().get(OPENEJB_CROSSCONTEXT_PROPERTY, false));
        standardContext.setNamingResources(new OpenEJBNamingResource(standardContext.getNamingResources()));

        String sessionManager = SystemInstance.get().getOptions().get(OPENEJB_SESSION_MANAGER_PROPERTY + "." + name, (String) null);
        if (sessionManager == null) {
            sessionManager = SystemInstance.get().getOptions().get(OPENEJB_SESSION_MANAGER_PROPERTY, (String) null);
        }
        if (sessionManager != null) {
            if (sessionManagerClass == null) {
                try { // the manager should be in standardclassloader
                    sessionManagerClass = ParentClassLoaderFinder.Helper.get().loadClass(sessionManager);
                } catch (final ClassNotFoundException e) {
                    LOGGER.error("can't find '" + sessionManager + "', StandardManager will be used", e);
                    sessionManagerClass = StandardManager.class;
                }
            }

            try {
                final Manager mgr = (Manager) sessionManagerClass.newInstance();
                standardContext.setManager(mgr);
            } catch (final Exception e) {
                LOGGER.error("can't instantiate '" + sessionManager + "', StandardManager will be used", e);
            }
        }

        final LifecycleListener[] listeners = standardContext.findLifecycleListeners();
        for (final LifecycleListener l : listeners) {
            if (l instanceof ContextConfig) {
                standardContext.removeLifecycleListener(l);
            }
        }
        standardContext.addLifecycleListener(new OpenEJBContextConfig(new StandardContextInfo(standardContext)));

        // force manually the namingContextListener to merge jndi in an easier way
        final NamingContextListener ncl = new NamingContextListener();
        try {
            ncl.setName((String) GET_NAMING_CONTEXT_NAME.invoke(standardContext));
        } catch (final Exception e) {
            ncl.setName(getId(standardContext));
        }
        ncl.setExceptionOnFailedWrite(standardContext.getJndiExceptionOnFailedWrite());
        standardContext.setNamingContextListener(ncl);
        standardContext.addLifecycleListener(ncl);
        standardContext.addLifecycleListener(new TomcatJavaJndiBinder());

        // listen some events
        standardContext.addContainerListener(new TomEEContainerListener());
    }

    public void initJ2EEInfo(final StandardContext standardContext) {
        if (initJEEInfo) {
            standardContext.setJ2EEServer(DEFAULT_J2EE_SERVER);

            final ContextInfo contextInfo = getContextInfo(standardContext);
            if (contextInfo == null || contextInfo.appInfo == null || contextInfo.appInfo.path == null) {
                standardContext.setJ2EEApplication(jmxName(standardContext.getName()));
            } else {
                standardContext.setJ2EEApplication(jmxName(shortName(contextInfo.appInfo.path)));
            }
        }
    }

    private String jmxName(final String name) { // see javax.management.ObjectName.construct()
        return name.replace(':', '_');
    }

    private String shortName(final String path) {
        if (path.contains("/")) {
            return path.substring(path.lastIndexOf('/'), path.length());
        }
        return path;
    }

    private static String finalName(final String path) {
        if (isRoot(path)) {
            return "/";
        }
        return path;
    }

    public ContextInfo getContextInfo(final String appName) {
        ContextInfo info = null;
        for (final Map.Entry<String, ContextInfo> current : infos.entrySet()) {
            final String key = current.getKey();
            if (key.equals(appName)) {
                info = current.getValue();
                break;
            }
            if (key.endsWith(appName)) {
                info = current.getValue();
            }
        }
        return info;
    }

    public class StandardContextInfo {

        private final StandardContext standardContext;

        public StandardContextInfo(final StandardContext standardContext) {
            this.standardContext = standardContext;
            if (standardContext == null) {
                final Throwable throwable = new Exception("StandardContext is null").fillInStackTrace();
                LOGGER.warning("StandardContext should not be null", throwable);
            }
        }

        public AppInfo app() {
            final ContextInfo contextInfo = getContextInfo(standardContext);
            if (contextInfo == null) {
                LOGGER.debug("No ContextInfo for StandardContext " + standardContext.getName());
                return null;
            }
            return contextInfo.appInfo;
        }

        public WebAppInfo get() {
            if (standardContext == null) {
                return null;
            }

            final ContextInfo contextInfo = getContextInfo(standardContext);
            if (contextInfo == null) {
                LOGGER.debug("No ContextInfo for StandardContext " + standardContext.getName());
                return null;
            }

            LOGGER.debug("contextInfo = " + contextInfo);
            LOGGER.debug("standardContext = " + standardContext);

            if (contextInfo.appInfo == null) {
                LOGGER.debug("ContextInfo has no AppInfo for StandardContext " + standardContext.getName());
                return null;
            }

            final String id = getId(standardContext);
            for (final WebAppInfo webApp : contextInfo.appInfo.webApps) {
                if (webApp == null) {
                    LOGGER.debug("ContextInfo.appInfo.webApps entry is null StandardContext " + standardContext.getName());
                    continue;
                }

                final String wId = getId(webApp.host, webApp.contextRoot, contextInfo.version);
                if (id.equals(wId)) {
                    return webApp;
                }
            }
            return null;
        }

        public ClassLoader loader() {
            if (standardContext != null && standardContext.getLoader() != null) {
                return standardContext.getLoader().getClassLoader();
            }
            return null;
        }

        @Override
        public String toString() {
            if (standardContext == null) {
                return super.toString();
            }

            return "StandardContextInfo{" +
                    "standardContext=" + standardContext +
                    '}';
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void beforeStart(final StandardContext standardContext) {
        if (standardContext.getResources() != null && LazyStopStandardRoot.class.isInstance(standardContext.getResources())) {
            // reset after reload
            Reflections.set(standardContext, "resources",  LazyStopStandardRoot.class.cast(standardContext.getResources()).getDelegate());
        }

        final ServletContext sc = standardContext.getServletContext();
        if (sc != null && !SystemInstance.get().getOptions().get(OPENEJB_JSESSION_ID_SUPPORT, true)) {
            final Set<SessionTrackingMode> defaultTrackingModes = sc.getEffectiveSessionTrackingModes();
            if (defaultTrackingModes.contains(SessionTrackingMode.URL)) {
                final Set<SessionTrackingMode> newModes = new HashSet<>();
                newModes.remove(SessionTrackingMode.URL);
                sc.setSessionTrackingModes(newModes);
            }
        }
        initContextLoader(standardContext);

        // used to add custom filters first - our arquillian integration uses it for instance
        // needs to be done now (= before start event) because of addFilterMapBefore() usage
        final String filters = SystemInstance.get().getProperty("org.apache.openejb.servlet.filters");
        if (filters != null) {
            final String[] names = filters.split(",");
            for (final String name : names) {
                final String[] clazzMapping = name.split("=");

                final FilterDef filterDef = new FilterDef();
                filterDef.setFilterClass(clazzMapping[0]);
                filterDef.setFilterName(clazzMapping[0]);
                standardContext.addFilterDef(filterDef);

                final FilterMap filterMap = new FilterMap();
                filterMap.setFilterName(clazzMapping[0]);
                filterMap.addURLPattern(clazzMapping[1]);
                standardContext.addFilterMapBefore(filterMap);
            }
        }

        // mainly to get back compatibility with tomcat <= 8.0
        final String cookieProcessor = SystemInstance.get().getProperty("tomee.tomcat.cookieProcessor");
        if (cookieProcessor != null) {
            // not that important for now if we use the container loader, we mainly want to be able to access
            // the legacy one
            final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
            try {
                final Class<?> cookieProcessorClass = contextClassLoader.loadClass(cookieProcessor.trim());
                standardContext.setCookieProcessor(CookieProcessor.class.cast(cookieProcessorClass.newInstance()));
            } catch (final Exception e) {
                throw new IllegalArgumentException("Cannot set CookieProcessor: " + cookieProcessor);
            }
        }
    }

    private void initContextLoader(final StandardContext standardContext) {
        final Loader standardContextLoader = standardContext.getLoader();
        if (standardContextLoader != null
                && (
                (!TomEEWebappLoader.class.equals(standardContextLoader.getClass())
                    && !WebappLoader.class.equals(standardContextLoader.getClass()))
                        || (WebappLoader.class.equals(standardContextLoader.getClass())
                                && !WebappLoader.class.cast(standardContextLoader).getLoaderClass().startsWith("org.apache.tom")))
                ) {
            // custom loader, we don't know it
            // and since we don't have a full delegate pattern for our lazy stop loader
            // simply skip lazy stop loader - normally sides effect will be an early shutdown for ears and some particular features
            // only affecting the app if the classes were not laoded at all
            return;
        }

        if (standardContextLoader != null && TomEEWebappLoader.class.isInstance(standardContextLoader)) {
            standardContextLoader.setContext(standardContext);
            return; // no need to replace the loader
        }

        // we just want to wrap it to lazy stop it (afterstop)
        // to avoid classnotfound in @PreDestoy or destroyApplication()
        final TomEEWebappLoader loader = new TomEEWebappLoader();
        loader.setDelegate(standardContext.getDelegate());
        loader.setLoaderClass(TomEEWebappClassLoader.class.getName());

        final Loader lazyStopLoader = new LazyStopLoader(loader);
        standardContext.setLoader(lazyStopLoader);
    }

    @Override
    public void configureStart(final LifecycleEvent event, final StandardContext standardContext) {
        final ContextTransaction contextTransaction = new ContextTransaction();
        contextTransaction.setProperty(org.apache.naming.factory.Constants.FACTORY, UserTransactionFactory.class.getName());
        standardContext.getNamingResources().setTransaction(contextTransaction);

        if (event != null) {
            // ensure NamingContext is available for eager usage (@Observes @Initialized(ApplicationScoped) for instance)
            standardContext.getNamingContextListener().lifecycleEvent(event);
        }

        TomcatHelper.configureJarScanner(standardContext);

        startInternal(standardContext);

        // clear a bit log for default case
        addMyFacesDefaultParameters(standardContext.getLoader().getClassLoader(), standardContext.getServletContext());

        // breaks cdi
        standardContext.setTldValidation(Boolean.parseBoolean(SystemInstance.get().getProperty("tomee.tld.validation", "false")));
        // breaks jstl
        standardContext.setXmlValidation(Boolean.parseBoolean(SystemInstance.get().getProperty("tomee.xml.validation", "false")));
    }

    @Override
    public void start(final StandardContext standardContext) {
        // nothing to do for now
    }

    /**
     * {@inheritDoc}
     */
//    @Override
    private void startInternal(final StandardContext standardContext) {
        if (isIgnored(standardContext)) {
            return;
        }

        if (shouldNotDeploy(standardContext)) {
            return;
        }

        final CoreContainerSystem cs = getContainerSystem();

        final Assembler a = getAssembler();
        if (a == null) {
            LOGGER.warning("OpenEJB has not been initialized so war will not be scanned for nested modules " + standardContext.getPath());
            return;
        }

        AppContext appContext = null;
        //Look for context info, maybe context is already scanned
        ContextInfo contextInfo = getContextInfo(standardContext);
        ClassLoader classLoader = standardContext.getLoader().getClassLoader();

        // bind jta before the app starts to ensure we have it in CDI
        final Thread thread = Thread.currentThread();
        final ClassLoader originalLoader = thread.getContextClassLoader();
        thread.setContextClassLoader(classLoader);

        final String listenerName = standardContext.getNamingContextListener().getName();
        ContextAccessController.setWritable(listenerName, standardContext.getNamingToken());
        try {
            final Context comp = Context.class.cast(ContextBindings.getClassLoader().lookup("comp"));

            // bind TransactionManager
            final TransactionManager transactionManager = SystemInstance.get().getComponent(TransactionManager.class);
            safeBind(comp, "TransactionManager", transactionManager);

            // bind TransactionSynchronizationRegistry
            final TransactionSynchronizationRegistry synchronizationRegistry = SystemInstance.get().getComponent(TransactionSynchronizationRegistry.class);
            safeBind(comp, "TransactionSynchronizationRegistry", synchronizationRegistry);
        } catch (final NamingException e) {
            // no-op
        } finally {
            thread.setContextClassLoader(originalLoader);
            ContextAccessController.setReadOnly(listenerName);
        }

        if (contextInfo == null) {
            final AppModule appModule = loadApplication(standardContext);
            appModule.getProperties().put("loader.from", "tomcat");

            final boolean skipTomeeResourceWrapping = !"true".equalsIgnoreCase(SystemInstance.get().getProperty("tomee.tomcat.resource.wrap", "true"));
            if (!skipTomeeResourceWrapping && OpenEJBNamingResource.class.isInstance(standardContext.getNamingResources())) {
                final Collection<String> importedNames = new ArrayList<>(); // we can get the same resource twice as in tomcat

                // add them to the app as resource
                final boolean forceDataSourceWrapping = "true".equalsIgnoreCase(SystemInstance.get().getProperty("tomee.tomcat.datasource.wrap", "false"));
                final OpenEJBNamingResource nr = (OpenEJBNamingResource) standardContext.getNamingResources();
                for (final ResourceBase resource : nr.getTomcatResources()) {
                    final String name = resource.getName();

                    // already init (org.apache.catalina.core.NamingContextListener.addResource())
                    // skip wrapping to ensure resource consistency
                    final boolean isDataSource = DataSource.class.getName().equals(resource.getType());
                    final boolean isAlreadyCreated = ContextResource.class.isInstance(resource) && ContextResource.class.cast(resource).getSingleton() && isDataSource;

                    if (!importedNames.contains(name)) {
                        importedNames.add(name);
                    } else {
                        continue;
                    }

                    boolean found = false;
                    for (final ResourceInfo r : SystemInstance.get().getComponent(OpenEjbConfiguration.class).facilities.resources) {
                        if (r.id.equals(name)) {
                            nr.removeResource(name);
                            found = true;
                            LOGGER.warning(name + " resource was defined in both tomcat and tomee so removing tomcat one");
                            break;
                        }
                    }

                    if (!found) {
                        final Resource newResource;

                        if (forceDataSourceWrapping || (!isAlreadyCreated && isDataSource)) { // we forward it to TomEE datasources
                            newResource = new Resource(name, resource.getType());

                            boolean jta = false;

                            final Properties properties = newResource.getProperties();
                            final Iterator<String> params = resource.listProperties();
                            while (params.hasNext()) {
                                final String paramName = params.next();
                                final String paramValue = (String) resource.getProperty(paramName);

                                // handling some param name conversion to OpenEJB style
                                if ("driverClassName".equals(paramName)) {
                                    properties.setProperty("JdbcDriver", paramValue);
                                } else if ("url".equals(paramName)) {
                                    properties.setProperty("JdbcUrl", paramValue);
                                } else {
                                    properties.setProperty(paramName, paramValue);
                                }

                                if ("JtaManaged".equalsIgnoreCase(paramName)) {
                                    jta = Boolean.parseBoolean(paramValue);
                                }
                            }

                            if (!jta) {
                                properties.setProperty("JtaManaged", "false");
                            }
                        } else { // custom type, let it be created
                            newResource = new Resource(name, resource.getType(), "org.apache.tomee:ProvidedByTomcat");

                            final Properties properties = newResource.getProperties();
                            properties.setProperty("jndiName", newResource.getId());
                            properties.setProperty("appName", getId(standardContext));
                            properties.setProperty("factory", (String) resource.getProperty("factory"));

                            final Reference reference = createReference(resource);
                            if (reference != null) {
                                properties.put("reference", reference);
                            }
                        }

                        appModule.getResources().add(newResource);
                    }
                }
            }

            if (appModule != null) {
                try {
                    contextInfo = addContextInfo(Contexts.getHostname(standardContext), standardContext);
                    contextInfo.standardContext = standardContext; // ensure to do it before an exception can be thrown

                    contextInfo.appInfo = configurationFactory.configureApplication(appModule);

                    final Boolean autoDeploy = DeployerEjb.AUTO_DEPLOY.get();
                    contextInfo.appInfo.autoDeploy = autoDeploy == null || autoDeploy;
                    DeployerEjb.AUTO_DEPLOY.remove();

                    if (!appModule.isWebapp()) {
                        classLoader = appModule.getClassLoader();
                    } else {
                        final ClassLoader loader = standardContext.getLoader().getClassLoader();
                        if (loader instanceof TomEEWebappClassLoader) {
                            final TomEEWebappClassLoader tomEEWebappClassLoader = (TomEEWebappClassLoader) loader;
                            for (final URL url : appModule.getWebModules().iterator().next().getAddedUrls()) {
                                tomEEWebappClassLoader.addURL(url);
                            }
                        }
                    }

                    setFinderOnContextConfig(standardContext, appModule);

                    servletContextHandler.getContexts().put(classLoader, standardContext.getServletContext());
                    try {
                        appContext = a.createApplication(contextInfo.appInfo, classLoader);
                    } finally {
                        servletContextHandler.getContexts().remove(classLoader);
                    }
                    // todo add watched resources to context

                    eagerInitOfLocalBeanProxies(appContext.getBeanContexts(), classLoader);
                } catch (final Exception e) {
                    LOGGER.error("Unable to deploy collapsed ear in war " + standardContext, e);
                    undeploy(standardContext, contextInfo);
                    // just to force tomee to start without EE part
                    if (System.getProperty(TomEESystemConfig.TOMEE_EAT_EXCEPTION_PROP) == null) {
                        final TomEERuntimeException tre = new TomEERuntimeException(e);
                        final DeploymentExceptionManager dem = SystemInstance.get().getComponent(DeploymentExceptionManager.class);
                        dem.saveDeploymentException(contextInfo.appInfo, tre);
                        throw tre;
                    }
                    return;
                }
            }
        } else {
            contextInfo.standardContext = standardContext;
            if (contextInfo.module != null && contextInfo.module.getFinder() != null) { // TODO: make it more explicit or less hacky not using properties
                final OpenEJBContextConfig openEJBContextConfig = findOpenEJBContextConfig(standardContext);
                if (openEJBContextConfig != null) {
                    openEJBContextConfig.finder(contextInfo.module.getFinder(), contextInfo.module.getClassLoader());
                }
            }
        }

        final String id = getId(standardContext);
        WebAppInfo webAppInfo = null;
        // appInfo is null when deployment fails
        if (contextInfo.appInfo != null) {
            for (final WebAppInfo w : contextInfo.appInfo.webApps) {
                if (id.equals(getId(w.host, w.contextRoot, contextInfo.version)) || id.equals(getId(w.host, w.moduleId, contextInfo.version))) {
                    if (webAppInfo == null) {
                        webAppInfo = w;
                    } else if (w.host != null && w.host.equals(Contexts.getHostname(standardContext))) {
                        webAppInfo = w;
                    }

                    break;
                }
            }

            if (appContext == null) {
                appContext = cs.getAppContext(contextInfo.appInfo.appId);
            }
        }

        if (webAppInfo != null) {

            if (appContext == null) {
                appContext = getContainerSystem().getAppContext(contextInfo.appInfo.appId);
            }

            // ensure matching (see getId() usage)
            webAppInfo.host = Contexts.getHostname(standardContext);
            webAppInfo.contextRoot = standardContext.getPath();

            // save jsf stuff
            final Map<String, Set<String>> scannedJsfClasses = new HashMap<>();
            for (final ClassListInfo info : webAppInfo.jsfAnnotatedClasses) {
                scannedJsfClasses.put(info.name, info.list);
            }
            jsfClasses.put(classLoader, scannedJsfClasses);

            try {

                // determine the injections
                final Set<Injection> injections = new HashSet<>();
                injections.addAll(appContext.getInjections());

                if (!contextInfo.appInfo.webAppAlone) {
                    updateInjections(injections, classLoader, false);
                    for (final BeanContext bean : appContext.getBeanContexts()) { // TODO: how if the same class in multiple webapps?
                        updateInjections(bean.getInjections(), classLoader, true);
                    }
                }
                injections.addAll(new InjectionBuilder(classLoader).buildInjections(webAppInfo.jndiEnc));

                // merge OpenEJB jndi into Tomcat jndi
                final TomcatJndiBuilder jndiBuilder = new TomcatJndiBuilder(standardContext, webAppInfo, injections);
                NamingUtil.setCurrentContext(standardContext);
                try {
                    jndiBuilder.mergeJndi();
                } finally {
                    NamingUtil.setCurrentContext(null);
                }

                // create EMF included in this webapp when nested in an ear
                for (final PersistenceUnitInfo unitInfo : contextInfo.appInfo.persistenceUnits) {
                    if (unitInfo.webappName != null && unitInfo.webappName.equals(webAppInfo.moduleId)) {
                        try {
                            final ReloadableEntityManagerFactory remf =
                                    (ReloadableEntityManagerFactory) SystemInstance.get().getComponent(ContainerSystem.class)
                                            .getJNDIContext().lookup(Assembler.PERSISTENCE_UNIT_NAMING_CONTEXT + unitInfo.id);
                            remf.overrideClassLoader(classLoader);
                            remf.createDelegate();
                        } catch (final NameNotFoundException nnfe) {
                            LOGGER.warning("Can't find " + unitInfo.id + " persistence unit");
                        }
                    }
                }

                // add WebDeploymentInfo to ContainerSystem
                final WebContext webContext = new WebContext(appContext);
                webContext.setServletContext(standardContext.getServletContext());
                webContext.setJndiEnc(new InitialContext());
                webContext.setClassLoader(classLoader);
                webContext.setId(webAppInfo.moduleId);
                webContext.setContextRoot(webAppInfo.contextRoot);
                webContext.setHost(webAppInfo.host);
                webContext.setBindings(new HashMap<String, Object>());
                webContext.getInjections().addAll(injections);
                appContext.getWebContexts().add(webContext);
                cs.addWebContext(webContext);
                standardContext.getServletContext().setAttribute("openejb.web.context", webContext);

                if (!contextInfo.appInfo.webAppAlone) {
                    final List<BeanContext> beanContexts = assembler.initEjbs(classLoader, contextInfo.appInfo, appContext, injections, new ArrayList<BeanContext>(), webAppInfo.moduleId);
                    OpenEJBLifecycle.CURRENT_APP_INFO.set(contextInfo.appInfo);
                    servletContextHandler.getContexts().put(classLoader, standardContext.getServletContext());
                    try {
                        new CdiBuilder().build(contextInfo.appInfo, appContext, beanContexts, webContext);
                    } catch (final Exception e) {
                        final DeploymentExceptionManager dem = SystemInstance.get().getComponent(DeploymentExceptionManager.class);
                        if (dem != null) {
                            dem.saveDeploymentException(contextInfo.appInfo, e);
                        }
                        throw e;
                    } finally {
                        servletContextHandler.getContexts().remove(classLoader);
                        OpenEJBLifecycle.CURRENT_APP_INFO.remove();
                    }
                    assembler.startEjbs(true, beanContexts);
                    assembler.bindGlobals(appContext.getBindings());
                    eagerInitOfLocalBeanProxies(beanContexts, standardContext.getLoader().getClassLoader());

                    deployWebServicesIfEjbCreatedHere(contextInfo.appInfo, beanContexts);
                }

                // jndi bindings
                webContext.getBindings().putAll(appContext.getBindings());
                webContext.getBindings().putAll(getJndiBuilder(classLoader, webAppInfo, injections, appContext.getProperties()).buildBindings(JndiEncBuilder.JndiScope.comp));

                final JavaeeInstanceManager instanceManager = new JavaeeInstanceManager(standardContext, webContext);
                standardContext.setInstanceManager(instanceManager);
                instanceManagers.put(classLoader, instanceManager);
                standardContext.getServletContext().setAttribute(InstanceManager.class.getName(), standardContext.getInstanceManager());
            } catch (final Exception e) {
                LOGGER.error("Error merging Java EE JNDI entries in to war " + standardContext.getPath() + ": Exception: " + e.getMessage(), e);
                if (System.getProperty(TomEESystemConfig.TOMEE_EAT_EXCEPTION_PROP) == null) {
                    final DeploymentExceptionManager dem = SystemInstance.get().getComponent(DeploymentExceptionManager.class);
                    if (dem != null && dem.getDeploymentException(contextInfo.appInfo) != null) {
                        if (RuntimeException.class.isInstance(e)) {
                            throw RuntimeException.class.cast(e);
                        }
                        throw new TomEERuntimeException(e);
                    }
                }
            }

            final WebBeansContext webBeansContext = appContext.getWebBeansContext();
            if (webBeansContext != null && webBeansContext.getBeanManagerImpl().isInUse()) {
                OpenEJBLifecycle.initializeServletContext(standardContext.getServletContext(), webBeansContext);
            }
        }

        // router
        final URL routerConfig = RouterValve.configurationURL(standardContext.getServletContext());
        if (routerConfig != null) {
            final RouterValve filter = new RouterValve();
            filter.setPrefix(standardContext.getName());
            filter.setConfigurationPath(routerConfig);
            standardContext.getPipeline().addValve(filter);
        }

        // register realm to have it in TomcatSecurityService
        final Realm realm = standardContext.getRealm();
        realms.put(standardContext.getName(), realm);
    }

    private static boolean shouldNotDeploy(final StandardContext standardContext) {
        if (StandardHost.class.isInstance(standardContext.getParent())) {
            final StandardHost host = StandardHost.class.cast(standardContext.getParent());
            if (host.getAutoDeploy() && standardContext.getDocBase() != null && 
                    standardContext.getDocBase() != null &&
                    new File(host.getAppBaseFile(), standardContext.getDocBase()).isDirectory() && (
                    new File(host.getAppBaseFile(), standardContext.getDocBase() + ".ear").exists() ||
                    new File(host.getAppBaseFile(), standardContext.getDocBase() + ".rar").exists())
            ) {

                LOGGER.info(String.format("Not deploying exploded directory %s as Java EE artifact exists which will be deployed.",
                        new File(host.getAppBaseFile(), standardContext.getPath()).getAbsolutePath()));

                return true;
            }
        }
        return false;
    }

    public void setFinderOnContextConfig(final StandardContext standardContext, final AppModule appModule) {
        final OpenEJBContextConfig openEJBContextConfig = findOpenEJBContextConfig(standardContext);
        if (openEJBContextConfig != null) {
            for (final EjbModule ejbModule : appModule.getEjbModules()) {
                if (ejbModule.getFile() != null && warPath(standardContext).equals(rootPath(ejbModule.getFile()))) {
                    openEJBContextConfig.finder(ejbModule.getFinder(), ejbModule.getClassLoader());
                    break;
                }
            }
        }
    }

    private OpenEJBContextConfig findOpenEJBContextConfig(StandardContext standardContext) {
        OpenEJBContextConfig openEJBContextConfig = null;
        for (final LifecycleListener listener : standardContext.findLifecycleListeners()) {
            if (OpenEJBContextConfig.class.isInstance(listener)) {
                openEJBContextConfig = OpenEJBContextConfig.class.cast(listener);
                break;
            }
        }
        return openEJBContextConfig;
    }

    private static File rootPath(final File file) {
        if (file.isDirectory() && file.getName().equals("classes") && file.getParentFile() != null && file.getParentFile().getName().equals("WEB-INF")) {
            final File parentFile = file.getParentFile().getParentFile();
            try {
                return parentFile.getCanonicalFile();
            } catch (final IOException e) {
                return parentFile;
            }
        }
        try {
            return file.getCanonicalFile();
        } catch (final IOException e) {
            return file;
        }
    }

    private static void deployWebServicesIfEjbCreatedHere(final AppInfo info, final Collection<BeanContext> beanContexts) {
        if (beanContexts == null || beanContexts.isEmpty()) {
            return;
        }
        SystemInstance.get().fireEvent(new NewEjbAvailableAfterApplicationCreated(info, beanContexts));
    }

    private static void eagerInitOfLocalBeanProxies(final Collection<BeanContext> beans, final ClassLoader classLoader) {
        for (final BeanContext deployment : beans) {
            if (deployment.isLocalbean() && !deployment.isDynamicallyImplemented()) { // init proxy eagerly otherwise deserialization of serialized object can't work
                final List<Class> interfaces = new ArrayList<>(2);
                interfaces.add(Serializable.class);
                interfaces.add(IntraVmProxy.class);
                final BeanType type = deployment.getComponentType();
                if (BeanType.STATEFUL.equals(type) || BeanType.MANAGED.equals(type)) {
                    interfaces.add(BeanContext.Removable.class);
                }
                try {
                    LocalBeanProxyFactory.createProxy(deployment.getBeanClass(), classLoader, interfaces.toArray(new Class<?>[interfaces.size()]));
                } catch (final Exception e) {
                    // no-op: as before
                }
            }
        }
    }

    private static Reference createReference(final ResourceBase resource) {
        final Reference ref;
        if (resource instanceof ContextResource) {
            final ContextResource cr = (ContextResource) resource;
            ref = new ResourceRef(resource.getType(), resource.getDescription(), cr.getScope(), cr.getAuth(), cr.getSingleton());
        } else {
            ref = new ResourceEnvRef(resource.getType());
        }

        final Iterator<String> params = resource.listProperties();
        while (params.hasNext()) {
            final String paramName = params.next();
            final String paramValue = (String) resource.getProperty(paramName);
            final StringRefAddr refAddr = new StringRefAddr(paramName, paramValue);
            ref.add(refAddr);
        }

        return ref;
    }

    private static void updateInjections(final Collection<Injection> injections, final ClassLoader classLoader, final boolean keepInjection) {
        final Iterator<Injection> it = injections.iterator();
        final List<Injection> newOnes = new ArrayList<>();
        while (it.hasNext()) {
            final Injection injection = it.next();
            if (injection.getTarget() == null) {
                try {
                    final Class<?> target = classLoader.loadClass(injection.getClassname());
                    if (keepInjection) {
                        final Injection added = new Injection(injection.getJndiName(), injection.getName(), target);
                        newOnes.add(added);
                    } else {
                        injection.setTarget(target);
                    }
                } catch (final ClassNotFoundException cnfe) {
                    // ignored
                }
            }
        }

        if (!newOnes.isEmpty()) {
            injections.addAll(newOnes);
        }
    }

    // return true if the dir can be deleted. TODO: revisit this heuristic
    private static boolean undeploy(final StandardContext standardContext, final ContextInfo contextInfo) {
        if (isReady(contextInfo.deployer)) {
            contextInfo.deployer.unmanageApp(standardContext.getName());
            return true;
        } else if (contextInfo.host != null) {
            return undeploy(standardContext, contextInfo.host);
        } else {
            Container container = contextInfo.standardContext;
            while (container != null) {
                if (container instanceof Host) {
                    break;
                }
                container = container.getParent();
            }
            return container != null && undeploy(standardContext, container);
        }
    }

    private static boolean undeploy(final StandardContext standardContext, final Container host) {
        final Container child = host.findChild(standardContext.getName());

        // skip undeployment if redeploying (StandardContext.redeploy())
        if (child instanceof org.apache.catalina.Context && org.apache.catalina.Context.class.cast(child).getPaused()) {
            return true;
        }

        // skip undeployment if restarting
        final TomEEWebappClassLoader tomEEWebappClassLoader = lazyClassLoader(
            org.apache.catalina.Context.class.isInstance(child) ? org.apache.catalina.Context.class.cast(child) : null);
        if (tomEEWebappClassLoader != null && tomEEWebappClassLoader.isRestarting()) {
            return true;
        }

        if (child != null) {
            host.removeChild(standardContext);
            return true;
        }
        return false;
    }

    private static TomEEWebappClassLoader lazyClassLoader(final org.apache.catalina.Context child) {
        if (child == null) {
            return null;
        }

        final Loader loader = child.getLoader();
        if (loader == null || !(loader instanceof LazyStopLoader)) {
            return null;
        }

        final ClassLoader old = ((LazyStopLoader) loader).getStopClassLoader();
        if (old == null || !(old instanceof TomEEWebappClassLoader)) {
            return null;
        }

        return (TomEEWebappClassLoader) old;
    }

    private JndiEncBuilder getJndiBuilder(final ClassLoader classLoader, final WebAppInfo webAppInfo, final Set<Injection> injections, final Properties props) throws OpenEJBException {
        return new JndiEncBuilder(webAppInfo.jndiEnc, injections, webAppInfo.moduleId, "Bean", null, webAppInfo.uniqueId, classLoader, props);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void afterStart(final StandardContext standardContext) {
        if (isIgnored(standardContext)) {
            return;
        }

        if (shouldNotDeploy(standardContext)) {
            return;
        }

        final Realm realm = standardContext.getRealm();
        final ClassLoader classLoader = standardContext.getLoader().getClassLoader();
        final Thread thread = Thread.currentThread();
        final ClassLoader originalLoader = thread.getContextClassLoader();
        if (realm != null && !(realm instanceof TomEERealm) && (standardContext.getParent() == null || (!realm.equals(standardContext.getParent().getRealm())))) {
            thread.setContextClassLoader(classLoader);
            try {
                standardContext.setRealm(tomeeRealm(realm));
            } finally {
                thread.setContextClassLoader(originalLoader);
            }
        }

        // if appInfo is null this is a failed deployment... just ignore
        final ContextInfo contextInfo = getContextInfo(standardContext);
        contextInfo.module = null; // shouldnt be there after startup (actually we shouldnt need it from info tree but our scanning does)
        if (contextInfo != null && contextInfo.appInfo == null) {
            return;
        } else if (contextInfo == null) { // openejb webapp loaded from the LoaderServlet
            return;
        }

        final String id = getId(standardContext);
        WebAppInfo currentWebAppInfo = null;
        for (final WebAppInfo webAppInfo : contextInfo.appInfo.webApps) {
            final String wId = getId(webAppInfo.host, webAppInfo.contextRoot, contextInfo.version);
            if (id.equals(wId)) {
                currentWebAppInfo = webAppInfo;
                break;
            }
        }

        // bind extra stuff at the java:comp level which can only be
        // bound after the context is created
        thread.setContextClassLoader(classLoader);

        final NamingContextListener ncl = standardContext.getNamingContextListener();
        final String listenerName = ncl.getName();
        ContextAccessController.setWritable(listenerName, standardContext.getNamingToken());
        try {
            final Context openejbContext = (Context) getContainerSystem().getJNDIContext().lookup("openejb");
            final Context root = (Context) ContextBindings.getClassLoader().lookup("");
            final Context comp = (Context) ContextBindings.getClassLoader().lookup("comp"); // usually fails

            // Context root = ncl.getNamingContext();
            // Context comp = (Context) root.lookup("comp");
            safeBind(root, "openejb", openejbContext);

            // add context to WebDeploymentInfo
            if (currentWebAppInfo != null) {
                final WebContext webContext = getContainerSystem().getWebContext(currentWebAppInfo.moduleId);
                if (webContext != null) {
                    webContext.setJndiEnc(root);
                }

                try {
                    // Bean Validation
                    standardContext.getServletContext().setAttribute("javax.faces.validator.beanValidator.ValidatorFactory", openejbContext.lookup(Assembler.VALIDATOR_FACTORY_NAMING_CONTEXT.replaceFirst("openejb", "") + currentWebAppInfo.uniqueId));
                } catch (final NamingException ne) {
                    LOGGER.warning("no validator factory found for webapp " + currentWebAppInfo.moduleId);
                }
            }

            try {
                final Class<?> orb = TomcatWebAppBuilder.class.getClassLoader().loadClass("org.omg.CORBA.ORB");
                if (SystemInstance.get().getComponent(orb) != null) {
                    safeBind(comp, "ORB", new SystemComponentReference(orb));
                }
            } catch (final NoClassDefFoundError | ClassNotFoundException cnfe) {
                // no-op
            }
            if (SystemInstance.get().getComponent(HandleDelegate.class) != null) {
                safeBind(comp, "HandleDelegate", new SystemComponentReference(HandleDelegate.class));
            }
        } catch (final NamingException e) {
            // no-op
        } finally {
            // required for Pojo Web Services because when Assembler creates the application
            // the CoreContainerSystem does not contain the WebContext
            // see also the start method getContainerSystem().addWebDeployment(webContext);
            try {
                servletContextHandler.getContexts().put(classLoader, standardContext.getServletContext());

                for (final WebAppInfo webAppInfo : contextInfo.appInfo.webApps) {
                    final String wId = getId(webAppInfo.host, webAppInfo.contextRoot, contextInfo.version);
                    if (id.equals(wId)) {
                        // Allow any post-deployment to happen without the RequestContext of a call to /tomee/ejb
                        final Request request = OpenEJBSecurityListener.requests.get();
                        OpenEJBSecurityListener.requests.remove();

                        SystemInstance.get().fireEvent(
                                new AfterApplicationCreated(contextInfo.appInfo,
                                                            webAppInfo,
                                                            standardContext.getServletContext()));

                        if (request != null) {
                            OpenEJBSecurityListener.requests.set(request);
                        }
                        break;
                    }
                }
            } finally {
                servletContextHandler.getContexts().remove(classLoader);
            }

            thread.setContextClassLoader(originalLoader);
            ContextAccessController.setReadOnly(listenerName);
        }

        thread.setContextClassLoader(classLoader);
        try {
            // owb integration filters
            final WebBeansContext webBeansContext = getWebBeansContext(contextInfo);
            if (webBeansContext != null) {
                // it is important to have a begin and a end listener
                // to be sure to create contexts before other listeners
                // and destroy contexts after other listeners

                final BeginWebBeansListener beginWebBeansListener = new BeginWebBeansListener(webBeansContext);
                final EndWebBeansListener endWebBeansListener = new EndWebBeansListener(webBeansContext);

                {
                    final Object[] appEventListeners = standardContext.getApplicationEventListeners();
                    final Object[] newEventListeners = new Object[appEventListeners.length + 2];

                    newEventListeners[0] = beginWebBeansListener;
                    System.arraycopy(appEventListeners, 0, newEventListeners, 1, appEventListeners.length);
                    newEventListeners[newEventListeners.length - 1] = endWebBeansListener;
                    standardContext.setApplicationEventListeners(newEventListeners);
                }

                {
                    final Object[] lifecycleListeners = standardContext.getApplicationLifecycleListeners();
                    final Object[] newLifecycleListeners = new Object[lifecycleListeners.length + 2];

                    newLifecycleListeners[0] = beginWebBeansListener;
                    System.arraycopy(lifecycleListeners, 0, newLifecycleListeners, 1, lifecycleListeners.length);
                    newLifecycleListeners[newLifecycleListeners.length - 1] = endWebBeansListener;
                    standardContext.setApplicationLifecycleListeners(newLifecycleListeners);
                }

                // also add the ThreadBindingListener to clean up async thread executions
                {
                    WebBeansThreadBindingListener webBeansThreadBindingListener = new WebBeansThreadBindingListener(webBeansContext, standardContext.getThreadBindingListener());
                    standardContext.setThreadBindingListener(webBeansThreadBindingListener);
                }

                final ContextsService contextsService = webBeansContext.getContextsService();
                if (CdiAppContextsService.class.isInstance(contextsService)) { // here ServletContext is usable
                    CdiAppContextsService.class.cast(contextsService).applicationStarted(standardContext.getServletContext());
                }
            } else {
                // just add the end listener to be able to stack tasks to execute at the request end
                final EndWebBeansListener endWebBeansListener = new EndWebBeansListener(webBeansContext);

                {
                    final Object[] appEventListeners = standardContext.getApplicationEventListeners();
                    final Object[] newEventListeners = new Object[appEventListeners.length + 1];

                    System.arraycopy(appEventListeners, 0, newEventListeners, 0, appEventListeners.length);
                    newEventListeners[newEventListeners.length - 1] = endWebBeansListener;
                    standardContext.setApplicationEventListeners(newEventListeners);
                }

                {
                    final Object[] lifecycleListeners = standardContext.getApplicationLifecycleListeners();
                    final Object[] newLifecycleListeners = new Object[lifecycleListeners.length + 1];

                    System.arraycopy(lifecycleListeners, 0, newLifecycleListeners, 0, lifecycleListeners.length);
                    newLifecycleListeners[newLifecycleListeners.length - 1] = endWebBeansListener;
                    standardContext.setApplicationLifecycleListeners(newLifecycleListeners);
                }
            }
        } finally {
            thread.setContextClassLoader(originalLoader);
        }

        LinkageErrorProtection.preload(standardContext);

        final Pipeline pipeline = standardContext.getPipeline();
        pipeline.addValve(new OpenEJBValve());

        final String[] valves = SystemInstance.get().getOptions().get("tomee.valves", "").split(" *, *");
        for (final String className : valves) {
            if ("".equals(className)) {
                continue;
            }
            try {
                final Class<?> clazz = classLoader.loadClass(className);
                if (Valve.class.isAssignableFrom(clazz)) {
                    final Valve valve = (Valve) clazz.newInstance();
                    pipeline.addValve(valve);
                }
            } catch (final Exception e) {
                LOGGER.error("can't add the valve " + className, e);
            }
        }

        // add servlets to webappinfo
        if (currentWebAppInfo != null) {
            for (final String mapping : standardContext.findServletMappings()) {
                final ServletInfo info = new ServletInfo();
                info.servletName = standardContext.findServletMapping(mapping);
                info.mappings.add(mapping);

                final Container container = standardContext.findChild(info.servletName);
                if (container instanceof StandardWrapper) {
                    info.servletClass = ((StandardWrapper) container).getServletClass();
                } else {
                    info.servletClass = mapping;
                }

                currentWebAppInfo.servlets.add(info);
            }
        }

        addConfiguredDocBases(standardContext, contextInfo);

        ensureMyFacesDontLooseFacesContext(standardContext);
    }

    private void ensureMyFacesDontLooseFacesContext(final StandardContext standardContext) {
        for (final Container w : standardContext.findChildren()) {
            if (!Wrapper.class.isInstance(w)) {
                continue;
            }
            final Wrapper wrapper = Wrapper.class.cast(w);
            if ("FacesServlet".equals(wrapper.getName()) && "javax.faces.webapp.FacesServlet".equals(wrapper.getServletClass())) {
                final ClassLoader loader = standardContext.getLoader().getClassLoader();
                try {
                    if (Files.toFile(loader.getResource("javax/faces/webapp/FacesServlet.class")).getName().startsWith("myfaces")) {
                        loader.loadClass("org.apache.tomee.myfaces.TomEEWorkaroundFacesServlet");
                        wrapper.setServletClass("org.apache.tomee.myfaces.TomEEWorkaroundFacesServlet");
                        break;
                    }
                } catch (final Throwable t) {
                    // not there, not a big deal in most of cases
                }
            }
        }
    }

    private static String appVersion(final AppInfo appInfo) {
        if (appInfo != null && appInfo.webAppAlone && appInfo.appId != null) {
            final int versionIndex = appInfo.appId.indexOf("##");
            return versionIndex >= 0 ? appInfo.appId.substring(versionIndex) : "";
        }
        return "";
    }

    private void addConfiguredDocBases(final StandardContext standardContext, final ContextInfo contextInfo) {
        if (contextInfo.appInfo.path != null) {   // add external web resources
            final String contextPath = standardContext.getServletContext().getContextPath();
            final String name = contextPath.isEmpty() ? "ROOT" : contextPath.substring(1);
            final String webResources = SystemInstance.get().getProperty("tomee." + name + ".docBases", contextInfo.appInfo.properties.getProperty("docBases"));
            if (webResources != null) {
                for (final String alt : webResources.trim().split(",")) {
                    final String trim = alt.trim();
                    if (trim.isEmpty()) {
                        continue;
                    }

                    if (!new File(trim).isDirectory()) {
                        LOGGER.warning("Can't add docBase which are not directory: " + trim);
                        continue;
                    }

                    final WebResourceRoot root = standardContext.getResources();
                    root.addPreResources(new DirResourceSet(root, "/", trim, "/"));
                }
            }
        }
    }

    private WebBeansContext getWebBeansContext(final ContextInfo contextInfo) {
        final AppContext appContext = getContainerSystem().getAppContext(contextInfo.appInfo.appId);

        if (appContext == null) {
            return null;
        }

        WebBeansContext webBeansContext = appContext.getWebBeansContext();

        if (webBeansContext == null) {
            return null;
        }

        for (final WebContext web : appContext.getWebContexts()) {
            final String stdName = removeFirstSlashAndWar(contextInfo.standardContext.getName());
            if (stdName == null) {
                continue;
            }

            final String name = removeFirstSlashAndWar(web.getContextRoot());
            if (stdName.equals(name)) {
                webBeansContext = web.getWebbeansContext();
                if (Contexts.getHostname(contextInfo.standardContext).equals(web.getHost())) {
                    break;
                } // else loop hoping to find a better matching
            }
        }

        if (webBeansContext == null) {
            webBeansContext = appContext.getWebBeansContext();
        }

        return webBeansContext;
    }

    private static String removeFirstSlashAndWar(final String name) {
        if (name == null || "/".equals(name) || name.isEmpty()) {
            return "";
        }

        String out = name;
        if (out.startsWith("/")) {
            out = out.substring(1);
        }
        if (out.endsWith(".war")) {
            return out.substring(0, Math.max(out.length() - 4, 0));
        }

        return out;
    }


    private static boolean isIgnored(final StandardContext standardContext) {
        // useful to disable web applications deployment
        // it can be placed in the context.xml file, server.xml, ...
        // see http://tomcat.apache.org/tomcat-5.5-doc/config/context.html#Context_Parameters
        return standardContext.getServletContext().getAttribute(IGNORE_CONTEXT) != null
                || standardContext.getServletContext().getInitParameter(IGNORE_CONTEXT) != null
                || standardContext instanceof IgnoredStandardContext
                || isExcludedBySystemProperty(standardContext);
    }

    private static boolean isExcludedBySystemProperty(final StandardContext standardContext) {
        String name = standardContext.getName();
        if (name == null) {
            name = standardContext.getPath();
            if (name == null) { // possible ?
                name = "";
            }
        }

        if (name.startsWith("/")) {
            name = name.substring(1);
        }

        final SystemInstance systemInstance = SystemInstance.get();
        return "true".equalsIgnoreCase(systemInstance.getProperty(name + ".tomcat-only", systemInstance.getProperty("tomcat-only", "false")));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void beforeStop(final StandardContext standardContext) {
        final ClassLoader classLoader = standardContext.getLoader().getClassLoader();

        // if it is not our custom loader clean up now otherwise wait afterStop
        if (!(standardContext.getLoader() instanceof LazyStopLoader)) {
            jsfClasses.remove(classLoader);
        }

        // ensure we can stop it lazily - before all was in the classloader, now we align webresourceroot on the classloader config
        // we wrap it only here to not modify at all runtime
        if (!LazyStopStandardRoot.class.isInstance(standardContext.getResources())
                && TomEEWebappClassLoader.class.isInstance(classLoader) && !TomEEWebappClassLoader.class.cast(classLoader).isForceStopPhase()) {
            final LazyStopStandardRoot standardRoot = new LazyStopStandardRoot(standardContext.getResources());
            Reflections.set(standardContext, "resources", standardRoot);
            TomEEWebappClassLoader.class.cast(classLoader).setWebResourceRoot(standardRoot); // cause Assembler relies on the classloader only
        }
    }

    private boolean isUnDeployable(final ContextInfo contextInfo) {
        return contextInfo.appInfo != null && contextInfo.deployer == null && contextInfo.appInfo.webAppAlone;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void stop(final StandardContext standardContext) {
        //No operation
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void afterStop(final StandardContext standardContext) {
        if (isIgnored(standardContext)) {
            return;
        }

        final TomEEWebappClassLoader old = lazyClassLoader(standardContext);
        if (old != null) { // should always be the case
            TldScanner.forceCompleteClean(old);
            jsfClasses.remove(old);
        }

        final ContextInfo contextInfo = getContextInfo(standardContext);
        boolean destroyFromTomcat = contextInfo != null && getAssembler().getDeployedApplications().contains(contextInfo.appInfo);
        if (destroyFromTomcat && isUnDeployable(contextInfo)) {
            contextInfo.appInfo.properties.setProperty("tomee.destroying", "true");
            try {
                getAssembler().destroyApplication(contextInfo.appInfo.path);
            } catch (final Exception e) {
                LOGGER.error("Unable to stop web application " + standardContext.getPath() + ": Exception: " + e.getMessage(), e);
            }
        } else {
            destroyFromTomcat = false;
        }

        NamingUtil.cleanUpContextResource(standardContext);

        if (old != null) {
            if (destroyFromTomcat) {
                try {
                    old.internalStop();
                } catch (final LifecycleException e) {
                    LOGGER.error("error stopping classloader of webapp " + standardContext.getName(), e);
                }
                ClassLoaderUtil.cleanOpenJPACache(old);
            }
            instanceManagers.remove(old);
        } else if (standardContext.getLoader() != null && standardContext.getLoader().getClassLoader() != null) {
            final ClassLoader classLoader = standardContext.getLoader().getClassLoader();
            instanceManagers.remove(classLoader);
        }
        realms.remove(standardContext.getName());

        if (contextInfo != null && (contextInfo.appInfo == null || contextInfo.appInfo.webAppAlone)) {
            removeContextInfo(standardContext);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void destroy(final StandardContext standardContext) {
        final Loader standardContextLoader = standardContext.getLoader();
        if (LazyStopLoader.class.isInstance(standardContextLoader)) {
            final Loader delegate = LazyStopLoader.class.cast(standardContextLoader).getDelegateLoader();
            if (TomEEWebappLoader.class.isInstance(delegate)) {
                final TomEEWebappLoader webappLoader = TomEEWebappLoader.class.cast(delegate);
                final ClassLoader loader = webappLoader.internalLoader();
                webappLoader.clearLoader();
                if (TomEEWebappClassLoader.class.isInstance(loader)) {
                    TomEEWebappClassLoader.class.cast(loader).internalDestroy();
                }
            }
        }

        final WebResourceRoot root = standardContext.getResources();
        if (LazyStopStandardRoot.class.isInstance(root)) {
            try {
                LazyStopStandardRoot.class.cast(root).internalDestroy();
            } catch (final LifecycleException e) {
                throw new IllegalStateException(e);
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public synchronized void afterStop(final StandardServer standardServer) {
        // clean ear based webapps after shutdown
        for (final ContextInfo contextInfo : infos.values()) {
            if (contextInfo != null && contextInfo.deployer != null) {
                final StandardContext standardContext = contextInfo.standardContext;
                final HostConfig deployer = contextInfo.deployer;
                deployer.unmanageApp(standardContext.getPath());
                final File realPath = Contexts.warPath(standardContext);
                if (realPath != null) {
                    deleteDir(realPath);
                }
            }
        }

        TomcatLoader.destroy();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public synchronized void checkHost(final StandardHost standardHost) {
        if (noHostCheck) {
            return;
        }
        if (standardHost.getAutoDeploy()) {
            // Undeploy any modified application
            for (final Iterator<Map.Entry<String, DeployedApplication>> iterator = deployedApps.entrySet().iterator(); iterator.hasNext(); ) {
                final Map.Entry<String, DeployedApplication> entry = iterator.next();
                final DeployedApplication deployedApplication = entry.getValue();
                if (deployedApplication.isModified()) { // TODO: for war use StandardContext.redeploy()
                    if (deployedApplication.appInfo != null) { // can happen with badly formed config
                        try {
                            getAssembler().destroyApplication(deployedApplication.appInfo.path);
                        } catch (final Exception e) {
                            LOGGER.error("Unable to application " + deployedApplication.appInfo.path, e);
                        }
                    } else {
                        LOGGER.error("appinfo is null for " + deployedApplication);
                    }
                    iterator.remove();
                }
            }

            // Deploy new applications
            final File appBase = appBase(standardHost);
            final File[] files = appBase.listFiles();
            if (null != files) {
                for (File file : files) {
                    if (file.getName().endsWith(".tmp")) { // tomcat is uploading, see org.apache.catalina.manager.ManagerServlet.deploy(java.io.PrintWriter, org.apache.catalina.util.ContextName, java.lang.String, boolean, javax.servlet.http.HttpServletRequest, org.apache.tomcat.util.res.StringManager)
                        continue;
                    }

                    final String name = file.getName();
                    // ignore war files
                    if (name.toLowerCase().endsWith(".war") || isRoot(name)
                            || name.equalsIgnoreCase("META-INF") || name.equalsIgnoreCase("WEB-INF")) {
                        continue;
                    }
                    // Simple fix for TOMEE-23
                    if (name.toLowerCase().equals(".ds_store")) {
                        continue;
                    }
                    // ignore unpacked web apps
                    if (file.isDirectory() && new File(file, "WEB-INF").exists()) {
                        continue;
                    }
                    // ignore unpacked apps where packed version is present (packed version is owner)
                    if (file.isDirectory() && (new File(file.getParent(), file.getName() + ".ear").exists()
                            || new File(file.getParent(), file.getName() + ".war").exists()
                            || new File(file.getParent(), file.getName() + ".rar").exists())) {
                        continue;
                    }
                    // ignore already deployed apps
                    if (isDeployed(file, standardHost)) {
                        continue;
                    }

                    final AppInfo appInfo;
                    try {
                        file = file.getCanonicalFile().getAbsoluteFile();
                        final AppModule appModule = deploymentLoader.load(file, null);

                        // 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) {
                            final WebModule webModule = appModule.getWebModules().iterator().next();
                            if (file.getAbsolutePath().equals(webModule.getJarLocation())) {
                                continue;
                            }
                        }

                        // tell web modules to deploy using this host
                        for (final WebModule webModule : appModule.getWebModules()) {
                            webModule.setHost(standardHost.getName());
                        }

                        appInfo = configurationFactory.configureApplication(appModule);
                        if (file.isFile() && file.getName().toLowerCase().endsWith(".ear")) {
                            // this is to prevent any WARs inside the EARs being unpacked in a directory where they'll then be deployed again
                            appInfo.properties.setProperty("tomcat.unpackWar", "false");
                        }

                        // if this is an unpacked dir, tomcat will pick it up as a webapp so undeploy it first
                        if (file.isDirectory()) {
                            final ContainerBase context = (ContainerBase) standardHost.findChild("/" + name);
                            if (context != null) {
                                try {
                                    standardHost.removeChild(context);
                                } catch (final Throwable t) {
                                    LOGGER.warning("Error undeploying wep application from Tomcat  " + name, t);
                                }
                                try {
                                    context.destroy();
                                } catch (final Throwable t) {
                                    LOGGER.warning("Error destroying Tomcat web context " + name, t);
                                }
                            }
                        }

                        getAssembler().createApplication(appInfo);

                        deployedApps.put(file.getAbsolutePath(), new DeployedApplication(file, appInfo));
                    } catch (final Throwable e) {
                        LOGGER.warning("Error deploying application " + file.getAbsolutePath(), e);
                    }
                }
            }
        }
    }

    /**
     * Returns true if given application is deployed
     * false otherwise.
     *
     * @param file         web application file
     * @param standardHost host
     * @return true if given application is deployed
     */
    private boolean isDeployed(final File file, final 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 (isRoot(name)) {
            name = "";
        }

        // can be a dir or a war so exists is fine
        return file.exists() && standardHost.findChild(name) != null;
    }

    /**
     * Returns application base of the given host.
     *
     * @param standardHost tomcat host
     * @return application base of the given host
     */
    protected File appBase(final 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 (final IOException e) {
            LOGGER.debug(e.getMessage(), e);
        }
        return file;
    }

    /**
     * Creates an openejb {@link AppModule} instance
     * from given tomcat context.
     *
     * @param standardContext tomcat context instance
     * @return a openejb application module
     */
    private AppModule loadApplication(final StandardContext standardContext) {
        // don't use getId since the app id shouldnt get the host (jndi)
        // final TomcatDeploymentLoader tomcatDeploymentLoader = new TomcatDeploymentLoader(standardContext, getId(standardContext));

        String id = standardContext.getName();
        if (id.startsWith("/")) {
            id = id.substring(1);
        }

        final TomcatDeploymentLoader tomcatDeploymentLoader = new TomcatDeploymentLoader(standardContext, id);
        final AppModule appModule;
        try {
            appModule = tomcatDeploymentLoader.load(Contexts.warPath(standardContext), configuredClasspath(standardContext));
        } catch (final OpenEJBException e) {
            throw new TomEERuntimeException(e);
        }

        // create the web module
        loadWebModule(appModule, standardContext);

        return appModule;
    }

    private static DeploymentLoader.ExternalConfiguration configuredClasspath(final StandardContext standardContext) {
        Loader loader = standardContext.getLoader();
        if (loader != null && LazyStopLoader.class.isInstance(loader)) {
            loader = LazyStopLoader.class.cast(loader).getDelegateLoader();
        }
        if (loader != null) {
            final ClassLoader cl = standardContext.getLoader().getClassLoader();
            if (cl == null) {
                return null;
            }

            final Collection<String> cp = new LinkedList<>();

            final WebResourceRoot webResources = standardContext.getResources();
            if (webResources != null) { // to enhance
                for (final WebResourceSet[] sets : asList(webResources.getPreResources(), webResources.getPostResources(), webResources.getJarResources())) {
                    for (final WebResourceSet wr : sets) {
                        final URL base = wr.getBaseUrl();
                        if (base != null) {
                            final File baseFile = URLs.toFile(base);
                            if (baseFile.isDirectory()) {
                                final String[] libs = wr.list("/WEB-INF/lib/");
                                if (libs != null) {
                                    for (final String resource : libs) {
                                        cp.add(new File(baseFile, resource).getAbsolutePath());
                                    }
                                }

                                final WebResource classes = wr.getResource("/WEB-INF/classes/");
                                if (classes != null) {
                                    final String path = classes.getCanonicalPath();
                                    if (path != null) {
                                        cp.add(path);
                                    }
                                }
                            } else if (baseFile.exists() && baseFile.getName().endsWith(".jar") && wr.getResource("/WEB-INF/classes/").exists()) {
                                try {
                                    cp.add(baseFile.getCanonicalPath());
                                } catch (final IOException e) {
                                    throw new IllegalStateException(e);
                                }
                            }
                        }
                    }
                }
            }

            if (!cp.isEmpty()) {
                return new DeploymentLoader.ExternalConfiguration(cp.toArray(new String[cp.size()]), null /*for now doesnt make sense, todo: configure*/);
            }
        }
        return null;
    }

    /**
     * Creates a new {@link WebModule} instance from given
     * tomcat context instance.
     *
     * @param standardContext tomcat context instance
     */
    private void loadWebModule(final AppModule appModule, final StandardContext standardContext) {
        final List<WebModule> webModules = appModule.getWebModules();

        if (webModules.isEmpty()) {
            final File file = appModule.getFile();
            LOGGER.error("Failed to find a single module in: " + file);
            return;
        }

        final WebModule webModule = webModules.get(0);
        final WebApp webApp = webModule.getWebApp();

        // create the web module
        final String path = standardContext.getPath();
        LOGGER.debug("context path = " + path);
        webModule.setHost(Contexts.getHostname(standardContext));
        // Add all Tomcat env entries to context so they can be overriden by the env.properties file
        final NamingResourcesImpl naming = standardContext.getNamingResources();
        for (final 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());
        }

        // remove all jndi entries where there is a configured Tomcat resource or resource-link
        for (final ContextResource resource : naming.findResources()) {
            final String name = resource.getName();
            removeRef(webApp, name);
        }
        for (final ContextResourceLink resourceLink : naming.findResourceLinks()) {
            final String name = resourceLink.getName();
            removeRef(webApp, name);
        }

        // remove all env entries from the web xml that are not overridable
        for (final ContextEnvironment environment : naming.findEnvironments()) {
            if (!environment.getOverride()) {
                // overrides are not allowed
                webApp.getEnvEntryMap().remove(environment.getName());
            }
        }
    }

    /**
     * Remove jndi references from related info map.
     *
     * @param webApp web application instance
     * @param name   jndi reference name
     */
    private void removeRef(final WebApp webApp, final 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);
    }

    /**
     * Binds given object into given component context.
     *
     * @param comp  context
     * @param name  name of the binding
     * @param value binded object
     */
    private void safeBind(final Context comp, final String name, final Object value) {
        try {
            comp.lookup(name);
            LOGGER.debug(name + " already bound, ignoring");
        } catch (final Exception e) {
            try {
                comp.bind(name, value);
            } catch (final NamingException ne) {
                LOGGER.error("Error in safeBind method", e);
            }
        }
    }

    /**
     * Gets openejb assembler instance.
     *
     * @return assembler
     */
    private Assembler getAssembler() {
        if (assembler == null) {
            assembler = (Assembler) SystemInstance.get().getComponent(org.apache.openejb.spi.Assembler.class);
        }
        return assembler;
    }

    /**
     * Gets container system for openejb.
     *
     * @return openejb container system
     */
    private CoreContainerSystem getContainerSystem() {
        if (containerSystem == null) {
            containerSystem = (CoreContainerSystem) SystemInstance.get().getComponent(ContainerSystem.class);
        }
        return containerSystem;
    }


    /**
     * Gets id of the context. Context id
     * is host name + context root name.
     *
     * @param standardContext context instance
     * @return id of the context
     */
    private String getId(final StandardContext standardContext) {
        return getId(Contexts.getHostname(standardContext), standardContext.getPath(), standardContext.getWebappVersion());
    }

    private String getId(final String host, final String context, final String version) {
        String contextRoot = context;
        if (isRoot(contextRoot)) {
            contextRoot = "";
        }
        if (!contextRoot.startsWith("/")) {
            contextRoot = "/" + contextRoot;
        }
        return (host == null ? hosts.getDefaultHost() : host) + contextRoot + (version == null || version.isEmpty() ? "" : (version.startsWith("##") ? version : "##" + version));
    }

    /**
     * Gets context info for given context.
     *
     * @param standardContext context
     * @return context info
     */
    public ContextInfo getContextInfo(final StandardContext standardContext) {
        final String id = getId(standardContext);
        final ContextInfo value;
        synchronized (infos) {
            value = infos.get(id);
        }
        return value;
    }

    /**
     * Gets context info for given web app info.
     *
     * @return context info
     */
    private synchronized ContextInfo getContextInfo(final String webAppHost, final String webAppContextRoot, final String version) {
        String host = webAppHost;
        if (host == null) {
            host = hosts.getDefaultHost();
        }

        final String id = getId(host, webAppContextRoot, version);

        final ContextInfo value;
        synchronized (infos) {
            value = infos.get(id);
        }
        return value;
    }

    /**
     * Add new context info.
     *
     * @param host            host name
     * @param standardContext context
     * @return context info
     */
    public ContextInfo addContextInfo(final String host, final StandardContext standardContext) {
        String contextRoot = standardContext.getName();
        if (!contextRoot.startsWith("/")) {
            contextRoot = "/" + contextRoot;
        }

        final String id = host + contextRoot;

        ContextInfo contextInfo;
        synchronized (infos) {
            contextInfo = infos.get(id);
            if (contextInfo == null) {
                contextInfo = new ContextInfo();
                final String webappVersion = standardContext.getWebappVersion();
                contextInfo.version = webappVersion != null && !webappVersion.isEmpty() ? "##" + webappVersion : webappVersion;
                contextInfo.standardContext = standardContext;
                infos.put(id, contextInfo);
            }
        }
        return contextInfo;
    }

    /**
     * Removes context info from map.
     *
     * @param standardContext context
     */
    private void removeContextInfo(final StandardContext standardContext) {
        boolean found = false;
        synchronized (infos) {
            final Iterator<Map.Entry<String, ContextInfo>> info = infos.entrySet().iterator();
            while (info.hasNext()) {
                if (info.next().getValue().standardContext == standardContext) {
                    info.remove();
                    found = true;
                    break;
                }
            }
        }
        if (!found) { // unlikely
            final String id = getId(standardContext);
            synchronized (infos) {
                infos.remove(id);
            }
        }
    }

    public static class ContextInfo {

        public AppInfo appInfo;
        public StandardContext standardContext;
        public HostConfig deployer;
        public Host host;
        public EjbModule module; // just during startup
        public String version;
        public Collection<String> resourceNames = Collections.emptyList();

        @Override
        public String toString() {
            return "ContextInfo{"
                    + "appInfo = " + appInfo + ", "
                    + "deployer = " + deployer + ", "
                    + "host = " + host
                    + "}";
        }
    }

    private static class DeployedApplication {

        private final AppInfo appInfo;
        private final Map<File, Long> watchedResource = new HashMap<>();

        public DeployedApplication(final File base, final AppInfo appInfo) {
            this.appInfo = appInfo;
            watchedResource.put(base, base.lastModified());
            if (appInfo != null) {
                for (final String resource : appInfo.watchedResources) {
                    final File file = new File(resource);
                    watchedResource.put(file, file.lastModified());
                }
                for (final EjbJarInfo info : appInfo.ejbJars) {
                    for (final String resource : info.watchedResources) {
                        final File file = new File(resource);
                        watchedResource.put(file, file.lastModified());
                    }
                }
                for (final WebAppInfo info : appInfo.webApps) {
                    for (final String resource : info.watchedResources) {
                        final File file = new File(resource);
                        watchedResource.put(file, file.lastModified());
                    }
                }
                for (final ConnectorInfo info : appInfo.connectors) {
                    for (final String resource : info.watchedResources) {
                        final File file = new File(resource);
                        watchedResource.put(file, file.lastModified());
                    }
                }
            }
        }

        public boolean isModified() {
            for (final Map.Entry<File, Long> entry : watchedResource.entrySet()) {
                final File file = entry.getKey();
                final long lastModified = entry.getValue();
                if ((!file.exists() && lastModified != 0L)
                        || (file.lastModified() != lastModified)) {
                    return true;
                }
            }
            return false;
        }
    }

    @Override
    public Map<ClassLoader, Map<String, Set<String>>> getJsfClasses() {
        return jsfClasses;
    }

    @Override
    public ClassLoader getParentClassLoader(final ClassLoader fallback) {
        return (null != this.parentClassLoader ? this.parentClassLoader : fallback);
    }

    public Map<String, Realm> getRealms() {
        return realms;
    }

    public Map<ClassLoader, InstanceManager> getInstanceManagers() {
        return instanceManagers;
    }
}
