private void startInternal()

in tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatWebAppBuilder.java [1179:1519]


    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);

                    CONTEXTS.put(classLoader, standardContext.getServletContext());
                    try {
                        appContext = a.createApplication(contextInfo.appInfo, classLoader);
                    } finally {
                        CONTEXTS.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);
                    CONTEXTS.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 {
                        CONTEXTS.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);
    }