All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.glassfish.weld.DeploymentImpl Maven / Gradle / Ivy

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 2009-2014 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */
// Portions Copyright [2016-2022] [Payara Foundation and/or its affiliates]

package org.glassfish.weld;

import com.sun.enterprise.container.common.spi.util.InjectionManager;
import static java.util.logging.Level.FINE;
import static java.util.logging.Level.WARNING;
import static java.util.stream.Collectors.toList;
import static org.glassfish.weld.connector.WeldUtils.*;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Supplier;
import java.util.logging.Logger;

import jakarta.enterprise.inject.spi.Extension;

import com.sun.enterprise.deploy.shared.ArchiveFactory;
import org.glassfish.api.deployment.DeploymentContext;
import org.glassfish.api.deployment.archive.ReadableArchive;
import org.glassfish.cdi.CDILoggerInfo;
import org.glassfish.deployment.common.DeploymentContextImpl;
import org.glassfish.deployment.common.InstalledLibrariesResolver;
import org.glassfish.hk2.classmodel.reflect.Types;
import org.glassfish.javaee.core.deployment.ApplicationHolder;
import org.glassfish.weld.connector.WeldUtils;
import org.glassfish.weld.connector.WeldUtils.BDAType;
import org.jboss.weld.bootstrap.WeldBootstrap;
import org.jboss.weld.bootstrap.api.ServiceRegistry;
import org.jboss.weld.bootstrap.api.helpers.SimpleServiceRegistry;
import org.jboss.weld.bootstrap.spi.BeanDeploymentArchive;
import org.jboss.weld.bootstrap.spi.BeanDiscoveryMode;
import org.jboss.weld.bootstrap.spi.BeansXml;
import org.jboss.weld.bootstrap.spi.CDI11Deployment;
import org.jboss.weld.bootstrap.spi.Metadata;
import org.jboss.weld.bootstrap.spi.helpers.MetadataImpl;

import com.sun.enterprise.deployment.EjbDescriptor;
import com.sun.enterprise.deployment.util.DOLUtils;
import org.glassfish.weld.services.InjectionServicesImpl;
import org.jboss.weld.injection.spi.InjectionServices;
import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension;
import org.jboss.weld.lite.extension.translator.LiteExtensionTranslator;
import java.security.PrivilegedAction;
import static java.lang.System.getSecurityManager;
import static java.security.AccessController.doPrivileged;
import jakarta.enterprise.inject.build.compatible.spi.SkipIfPortableExtensionPresent;


/*
 * Represents a deployment of a CDI (Weld) application.
 */
public class DeploymentImpl implements CDI11Deployment {

    // Keep track of our BDAs for this deployment
    private List rarRootBdas;
    private List ejbRootBdas;
    private List warRootBdas;
    private List libJarRootBdas = null;

    private List beanDeploymentArchives = new ArrayList<>();
    private DeploymentContext context;

    // A convenience Map to get BDA for a given BDA ID
    private Map idToBeanDeploymentArchive = new HashMap<>();
    private SimpleServiceRegistry simpleServiceRegistry = null;

    private Logger logger = CDILoggerInfo.getLogger();

    // holds BDA's created for extensions
    private Map extensionBDAMap = new HashMap<>();

    private Iterable> extensions;

    private List> dynamicExtensions = new ArrayList<>();

    private Collection deployedEjbs = new LinkedList<>();
    private ArchiveFactory archiveFactory;

    private boolean earContextAppLibBdasProcessed = false;

    private String appName;
    private String contextId;
    final InjectionManager injectionManager;

    /**
     * Produce BeanDeploymentArchives for this Deployment
     * from information from the provided ReadableArchive.
     */
    public DeploymentImpl(ReadableArchive archive,
                          Collection ejbs,
                          DeploymentContext context,
                          ArchiveFactory archiveFactory,
                          String moduleName,
                          InjectionManager injectionManager) {
        if ( logger.isLoggable( FINE ) ) {
            logger.log(FINE, CDILoggerInfo.CREATING_DEPLOYMENT_ARCHIVE, new Object[]{ archive.getName()});
        }
        this.archiveFactory = archiveFactory;
        this.context = context;
        this.injectionManager = injectionManager;

        // Collect /lib Jar BDAs (if any) from the parent module.
        // If we've produced BDA(s) from any /lib jars, return as
        // additional BDA(s) will be produced for any subarchives (war/jar).
        libJarRootBdas = scanForLibJars(archive, ejbs, context);
        if ((libJarRootBdas != null) && !libJarRootBdas.isEmpty()) {
            return;
        }

        ApplicationHolder holder = context.getModuleMetaData(ApplicationHolder.class);
        if ((holder != null) && (holder.app != null)) {
            this.appName = holder.app.getAppName();
        } else if(moduleName != null) {
            this.appName = moduleName;
        } else {
            this.appName = "CDIApp";
        }

        this.contextId = moduleName != null? moduleName : archive.getName();
        createModuleBda(archive, ejbs, context, contextId);
    }

    private void addBeanDeploymentArchives(RootBeanDeploymentArchive bda) {
        BDAType moduleBDAType = bda.getModuleBDAType();
        if (moduleBDAType.equals(BDAType.WAR)) {
            if (warRootBdas == null) {
                warRootBdas = new ArrayList<>();
            }
            warRootBdas.add(bda);
        } else if (moduleBDAType.equals(BDAType.JAR)) {
            if (ejbRootBdas == null) {
                ejbRootBdas = new ArrayList<>();
            }
            ejbRootBdas.add(bda);
        } else if (moduleBDAType.equals(BDAType.RAR)) {
            if (rarRootBdas == null) {
                rarRootBdas = new ArrayList<>();
            }
            rarRootBdas.add(bda);
        }
    }

    /**
     * Produce BeanDeploymentArchives for this Deployment
     * from information from the provided ReadableArchive.
     * This method is called for subsequent modules after This Deployment has
     * been created.
     */
    public void scanArchive(ReadableArchive archive, Collection ejbs, DeploymentContext context, String moduleName) {
        if (libJarRootBdas == null) {
            libJarRootBdas = scanForLibJars(archive, ejbs, context);
            if ((libJarRootBdas != null) && !libJarRootBdas.isEmpty()) {
                return;
            }
        }

        this.context = context;
        createModuleBda(archive, ejbs, context, moduleName);
    }

    /**
     * Build the accessibility relationship between BeanDeploymentArchives
     * for this Deployment.  This method must be called after all Weld
     * BeanDeploymentArchives have been produced for the
     * Deployment.
     */
    public void buildDeploymentGraph() {
        // Make jars accessible to each other - Example:
        //    /ejb1.jar <----> /ejb2.jar
        // If there are any application (/lib) jars, make them accessible

        if (ejbRootBdas != null) {
            for (RootBeanDeploymentArchive ejbRootBda : ejbRootBdas) {
                BeanDeploymentArchive ejbModuleBda = ejbRootBda.getModuleBda();

                boolean modifiedArchive = false;
                for (RootBeanDeploymentArchive otherEjbRootBda : ejbRootBdas) {
                    BeanDeploymentArchive otherEjbModuleBda = otherEjbRootBda.getModuleBda();
                    if (otherEjbModuleBda.getId().equals(ejbModuleBda.getId())) {
                        continue;
                    }
                    ejbRootBda.getBeanDeploymentArchives().add(otherEjbRootBda);
                    ejbRootBda.getBeanDeploymentArchives().add(otherEjbModuleBda);
                    ejbModuleBda.getBeanDeploymentArchives().add(otherEjbModuleBda);
                    modifiedArchive = true;
                }

                // Make /lib jars accessible to the ejbs.
                if (libJarRootBdas != null) {
                    for (RootBeanDeploymentArchive libJarRootBda : libJarRootBdas) {
                        BeanDeploymentArchive libJarModuleBda = libJarRootBda.getModuleBda();
                        ejbRootBda.getBeanDeploymentArchives().add(libJarRootBda);
                        ejbRootBda.getBeanDeploymentArchives().add(libJarModuleBda);
                        ejbModuleBda.getBeanDeploymentArchives().add(libJarRootBda);
                        ejbModuleBda.getBeanDeploymentArchives().add(libJarModuleBda);
                        modifiedArchive = true;
                    }
                }

                // Make rars accessible to ejbs
                if (rarRootBdas != null) {
                    for (RootBeanDeploymentArchive rarRootBda : rarRootBdas) {
                        BeanDeploymentArchive rarModuleBda = rarRootBda.getModuleBda();
                        ejbRootBda.getBeanDeploymentArchives().add(rarRootBda);
                        ejbRootBda.getBeanDeploymentArchives().add(rarModuleBda);
                        ejbModuleBda.getBeanDeploymentArchives().add(rarRootBda);
                        ejbModuleBda.getBeanDeploymentArchives().add(rarModuleBda);
                        modifiedArchive = true;
                    }
                }

                if (modifiedArchive) {
                    int idx = getBeanDeploymentArchives().indexOf(ejbModuleBda);
                    if (idx >= 0) {
                        getBeanDeploymentArchives().remove(idx);
                        getBeanDeploymentArchives().add(ejbModuleBda);
                    }
                }
            }
        }

        // Make jars (external to WAR modules) accessible to WAR BDAs - Example:
        //    /web.war ----> /ejb.jar
        // If there are any application (/lib) jars, make them accessible

        if (warRootBdas != null) {
            ListIterator warIter = warRootBdas.listIterator();
            boolean modifiedArchive = false;
            while (warIter.hasNext()) {
                RootBeanDeploymentArchive warRootBda = warIter.next();
                BeanDeploymentArchive warModuleBda = warRootBda.getModuleBda();
                if (ejbRootBdas != null) {
                    for (RootBeanDeploymentArchive ejbRootBda : ejbRootBdas) {
                        BeanDeploymentArchive ejbModuleBda = ejbRootBda.getModuleBda();
                        warRootBda.getBeanDeploymentArchives().add(ejbRootBda);
                        warRootBda.getBeanDeploymentArchives().add(ejbModuleBda);
                        warModuleBda.getBeanDeploymentArchives().add(ejbRootBda);
                        warModuleBda.getBeanDeploymentArchives().add(ejbModuleBda);

                       for ( BeanDeploymentArchive oneBda : warModuleBda.getBeanDeploymentArchives() ) {
                         oneBda.getBeanDeploymentArchives().add( ejbRootBda );
                         oneBda.getBeanDeploymentArchives().add( ejbModuleBda );
                       }

                      modifiedArchive = true;
                    }
                }

                // Make /lib jars accessible to the war and it's sub bdas
                if (libJarRootBdas != null) {
                    for (RootBeanDeploymentArchive libJarRootBda : libJarRootBdas) {
                        BeanDeploymentArchive libJarModuleBda = libJarRootBda.getModuleBda();
                        warRootBda.getBeanDeploymentArchives().add(libJarRootBda);
                        warRootBda.getBeanDeploymentArchives().add(libJarModuleBda);
                        warModuleBda.getBeanDeploymentArchives().add(libJarRootBda);
                        warModuleBda.getBeanDeploymentArchives().add(libJarModuleBda);

                        for ( BeanDeploymentArchive oneBda : warModuleBda.getBeanDeploymentArchives() ) {
                          oneBda.getBeanDeploymentArchives().add( libJarRootBda );
                          oneBda.getBeanDeploymentArchives().add( libJarModuleBda );
                        }

                        modifiedArchive = true;
                    }
                }

                // Make rars accessible to wars and it's sub bdas
                if (rarRootBdas != null) {
                    for (RootBeanDeploymentArchive rarRootBda : rarRootBdas) {
                        BeanDeploymentArchive rarModuleBda = rarRootBda.getModuleBda();
                        warRootBda.getBeanDeploymentArchives().add(rarRootBda);
                        warRootBda.getBeanDeploymentArchives().add(rarModuleBda);
                        warModuleBda.getBeanDeploymentArchives().add(rarRootBda);
                        warModuleBda.getBeanDeploymentArchives().add(rarModuleBda);

                      for ( BeanDeploymentArchive oneBda : warModuleBda.getBeanDeploymentArchives() ) {
                        oneBda.getBeanDeploymentArchives().add( rarRootBda );
                        oneBda.getBeanDeploymentArchives().add( rarModuleBda );
                      }

                      modifiedArchive = true;
                    }
                }

                if (modifiedArchive) {
                    int idx = getBeanDeploymentArchives().indexOf(warModuleBda);
                    if (idx >= 0) {
                        getBeanDeploymentArchives().remove(idx);
                        getBeanDeploymentArchives().add(warModuleBda);
                    }
                    modifiedArchive = false;
                }
            }
        }

        addDependentBdas();
    }

    private void addDependentBdas() {
        Set additionalBdas = new HashSet<>();
        for ( BeanDeploymentArchive oneBda : beanDeploymentArchives ) {
            BeanDeploymentArchiveImpl beanDeploymentArchiveImpl = ( BeanDeploymentArchiveImpl ) oneBda;
            Collection subBdas = beanDeploymentArchiveImpl.getBeanDeploymentArchives();
            for (BeanDeploymentArchive subBda : subBdas) {
                if ( !subBda.getBeanClasses().isEmpty() ) {
                    // only add it if it's cdi-enabled (contains at least one bean that is managed by cdi)
                    additionalBdas.add(subBda);
                }
            }
        }

        for ( BeanDeploymentArchive oneBda : additionalBdas ) {
            if ( ! beanDeploymentArchives.contains( oneBda ) ) {
                beanDeploymentArchives.add( oneBda );
            }
        }
    }

    @Override
    public List getBeanDeploymentArchives() {
        if ( logger.isLoggable( FINE ) ) {
            logger.log(FINE, CDILoggerInfo.GET_BEAN_DEPLOYMENT_ARCHIVES, new Object[] {beanDeploymentArchives});
        }
        return beanDeploymentArchives;
    }

    @Override
    public BeanDeploymentArchive loadBeanDeploymentArchive(Class beanClass) {
        if ( logger.isLoggable( FINE ) ) {
            logger.log(FINE, CDILoggerInfo.LOAD_BEAN_DEPLOYMENT_ARCHIVE, new Object[] { beanClass });
        }
        List beanDeploymentArchives = getBeanDeploymentArchives();

        ListIterator lIter = beanDeploymentArchives.listIterator();
        while (lIter.hasNext()) {
            BeanDeploymentArchive bda = lIter.next();
            if ( logger.isLoggable( FINE ) ) {
                logger.log(FINE,
                           CDILoggerInfo.LOAD_BEAN_DEPLOYMENT_ARCHIVE_CHECKING,
                           new Object[] { beanClass, bda.getId() });
            }
            if (((BeanDeploymentArchiveImpl)bda).getModuleBeanClasses().contains(beanClass.getName())) {
                //don't stuff this Bean Class into the BDA's beanClasses,
                //as Weld automatically add theses classes to the BDA's bean Classes
                if ( logger.isLoggable( FINE ) ) {
                    logger.log(FINE,
                               CDILoggerInfo.LOAD_BEAN_DEPLOYMENT_ARCHIVE_ADD_TO_EXISTING,
                               new Object[] {beanClass.getName(), bda });
                }
                return bda;
            }

            //XXX: As of now, we handle one-level. Ideally, a bean deployment
            //descriptor is a composite and we should be able to search the tree
            //and get the right BDA for the beanClass
            if (!bda.getBeanDeploymentArchives().isEmpty()) {
                for(BeanDeploymentArchive subBda: bda.getBeanDeploymentArchives()){
                    Collection moduleBeanClassNames = ((BeanDeploymentArchiveImpl)subBda).getModuleBeanClasses();
                    if ( logger.isLoggable( FINE ) ) {
                        logger.log(FINE,
                                   CDILoggerInfo.LOAD_BEAN_DEPLOYMENT_ARCHIVE_CHECKING_SUBBDA,
                                   new Object[] {beanClass, subBda.getId()});
                    }
                    boolean match = moduleBeanClassNames.contains(beanClass.getName());
                    if (match) {
                        //don't stuff this Bean Class into the BDA's beanClasses,
                        //as Weld automatically add theses classes to the BDA's bean Classes
                        if ( logger.isLoggable( FINE ) ) {
                            logger.log(FINE,
                                       CDILoggerInfo.LOAD_BEAN_DEPLOYMENT_ARCHIVE_ADD_TO_EXISTING,
                                       new Object[]{ beanClass.getName(), subBda});
                        }
                        return subBda;
                    }
                }
            }
        }

        BeanDeploymentArchive extensionBDA = extensionBDAMap.get(beanClass.getClassLoader());
        if ( extensionBDA != null ) {
            return extensionBDA;
        }

        // If the BDA was not found for the Class, create one and add it
        if ( logger.isLoggable( FINE ) ) {
            logger.log(FINE, CDILoggerInfo.LOAD_BEAN_DEPLOYMENT_ARCHIVE_CREATE_NEW_BDA, new Object []{beanClass});
        }
        List> beanClasses = new ArrayList<>();
        List beanXMLUrls = new CopyOnWriteArrayList<>();
        Set ejbs = new HashSet<>();
        beanClasses.add(beanClass);
        BeanDeploymentArchive newBda =
            new BeanDeploymentArchiveImpl(beanClass.getName(),
                                          beanClasses, beanXMLUrls, ejbs, context);
        // have to create new InjectionServicesImpl for each new BDA so injection context is propagated for the correct bundle
        newBda.getServices().add(InjectionServices.class, new InjectionServicesImpl(injectionManager, DOLUtils.getCurrentBundleForContext(context), this));
        BeansXml beansXml = newBda.getBeansXml();
        if (beansXml == null || !beansXml.getBeanDiscoveryMode().equals(BeanDiscoveryMode.NONE)) {
            if ( logger.isLoggable( FINE ) ) {
                logger.log(FINE,
                           CDILoggerInfo.LOAD_BEAN_DEPLOYMENT_ARCHIVE_ADD_NEW_BDA_TO_ROOTS,
                           new Object[] {} );
            }
            lIter = beanDeploymentArchives.listIterator();
            while (lIter.hasNext()) {
                BeanDeploymentArchive bda = lIter.next();
                bda.getBeanDeploymentArchives().add(newBda);
            }
            if ( logger.isLoggable( FINE ) ) {
                logger.log(FINE,
                           CDILoggerInfo.LOAD_BEAN_DEPLOYMENT_ARCHIVE_RETURNING_NEWLY_CREATED_BDA,
                           new Object[]{beanClass, newBda});
            }
            beanDeploymentArchives.add(newBda);

            // Make all previously found extension BDAs visible to this extension BDA
            newBda.getBeanDeploymentArchives().addAll(extensionBDAMap.values());

            idToBeanDeploymentArchive.put(newBda.getId(), newBda);
            extensionBDAMap.put( beanClass.getClassLoader(), newBda);
            return newBda;
        }

        return null;
    }

    @Override
    public ServiceRegistry getServices() {
        if (simpleServiceRegistry == null) {
            simpleServiceRegistry = new SimpleServiceRegistry();
        }
        return simpleServiceRegistry;
    }

    @Override
    public Iterable> getExtensions() {
        if (extensions != null) {
            return extensions;
        }

        List bdas = getBeanDeploymentArchives();
        ArrayList> extnList = new ArrayList<>();

        //registering the org.jboss.weld.lite.extension.translator.LiteExtensionTranslator
        //to be able to execute build compatible extensions
        List> buildExtensions = getBuildCompatibleExtensions();
        if (!buildExtensions.isEmpty()) {
            try {
                LiteExtensionTranslator extensionTranslator = getSecurityManager() != null ?
                        doPrivileged(new PrivilegedAction() {
                            @Override
                            public LiteExtensionTranslator run() {
                                return new LiteExtensionTranslator(buildExtensions, Thread.currentThread().getContextClassLoader());
                            }
                        }): new LiteExtensionTranslator(buildExtensions, Thread.currentThread().getContextClassLoader());
                extnList.add(new MetadataImpl<>(extensionTranslator));
            } catch(Exception e) {
                logger.log(WARNING, "Problem to register CDI Build Compatible Extensions");
                throw new RuntimeException(e);
            }
        }

        // Track classloaders to ensure we don't scan the same classloader twice
        HashSet scannedClassLoaders = new HashSet<>();

        // ensure we don't add the same extension twice
        HashMap,Metadata> loadedExtensions = new HashMap<>();

        for (BeanDeploymentArchive bda : bdas) {
            if (!(bda instanceof RootBeanDeploymentArchive)) {
                ClassLoader moduleClassLoader = ((BeanDeploymentArchiveImpl)bda).getModuleClassLoaderForBDA();
                if (!scannedClassLoaders.contains(moduleClassLoader)) {
                    scannedClassLoaders.add(moduleClassLoader);
                    extensions = context.getTransientAppMetaData(WeldDeployer.WELD_BOOTSTRAP,
                                                                 WeldBootstrap.class).loadExtensions(moduleClassLoader);
                    if (extensions != null) {
                        for (Metadata bdaExtn : extensions) {
                            if (loadedExtensions.get(bdaExtn.getValue().getClass()) == null) {
                                extnList.add(bdaExtn);
                                loadedExtensions.put(bdaExtn.getValue().getClass(), bdaExtn);
                            }
                        }
                    }
                }
            }
        }

        // Load sniffer extensions
        @SuppressWarnings("unchecked")
        Iterable> snifferExtensions = context.getTransientAppMetaData(WeldDeployer.SNIFFER_EXTENSIONS, Iterable.class);
        if (snifferExtensions != null) {
            for (Supplier extensionCreator : snifferExtensions) {
                final Extension extension = extensionCreator.get();
                final Class extensionClass = extension.getClass();
                final Metadata extensionMetadata = new MetadataImpl<>(extension, extensionClass.getName());
                extnList.add(extensionMetadata);
            }
        }

        extnList.addAll(dynamicExtensions);
        extensions = extnList;
        return extnList;
    }

    public boolean addDynamicExtension(Metadata extension) {
        return dynamicExtensions.add(extension);
    }

    public boolean removeDynamicExtension(Metadata extension) {
        return dynamicExtensions.remove(extension);
    }

    public void clearDynamicExtensions() {
        dynamicExtensions.clear();
    }

    @Override
    public String toString() {
        StringBuilder valBuff = new StringBuilder();
        List beanDeploymentArchives = getBeanDeploymentArchives();
        ListIterator lIter = beanDeploymentArchives.listIterator();
        while (lIter.hasNext()) {
            BeanDeploymentArchive bda = lIter.next();
            valBuff.append(bda.toString());
        }
        return valBuff.toString();
    }

    public BeanDeploymentArchive getBeanDeploymentArchiveForArchive(String archiveId) {
        return idToBeanDeploymentArchive.get(archiveId);
    }

    public void cleanup() {
        if (ejbRootBdas != null) {
            ejbRootBdas.clear();
        }
        if (warRootBdas != null) {
            warRootBdas.clear();
        }
        if (libJarRootBdas != null) {
            libJarRootBdas.clear();
        }

        if ( rarRootBdas != null ) {
            rarRootBdas.clear();
        }

        if (idToBeanDeploymentArchive != null) {
            idToBeanDeploymentArchive.clear();
        }
    }

    private List> getBuildCompatibleExtensions() {
        return
                ServiceLoader.load(BuildCompatibleExtension.class, Thread.currentThread().getContextClassLoader())
                        .stream()
                        .map(java.util.ServiceLoader.Provider::get)
                        .map(e -> e.getClass())
                        .filter(e -> !e.isAnnotationPresent(SkipIfPortableExtensionPresent.class))
                        .collect(toList());
    }

    // This method creates and returns a List of BeanDeploymentArchives for each
    // Weld enabled jar under /lib of an existing Archive.
    private List scanForLibJars( ReadableArchive archive,
                                                            Collection ejbs,
                                                            DeploymentContext context) {
        List libJars = null;
        ApplicationHolder holder = context.getModuleMetaData(ApplicationHolder.class);
        if ((holder != null) && (holder.app != null)) {
            String libDir = holder.app.getLibraryDirectory();
            if (libDir != null && !libDir.isEmpty()) {
                Enumeration entries = archive.entries(libDir);
                while (entries.hasMoreElements()) {
                    final String entryName = entries.nextElement();

                    // if a jar is directly in lib dir and not WEB-INF/lib/foo/bar.jar
                    if (DOLUtils.isScanningAllowed(holder.app, entryName) && entryName.endsWith(JAR_SUFFIX) &&
                        entryName.indexOf(SEPARATOR_CHAR, libDir.length() + 1 ) == -1 ) {
                        try {
                            ReadableArchive jarInLib = archive.getSubArchive(entryName);
                            if (jarInLib != null && (jarInLib.exists(META_INF_BEANS_XML) || WeldUtils.isImplicitBeanArchive(context, jarInLib))) {
                                if (libJars == null) {
                                    libJars = new ArrayList<>();
                                }
                                libJars.add(jarInLib);
                            }
                        } catch (IOException e) {
                            logger.log(FINE, CDILoggerInfo.EXCEPTION_SCANNING_JARS, new Object[]{e});
                        }
                    }
                }
            }
        }

        if (libJars != null) {
            String libDir = holder.app.getLibraryDirectory();
            for (ReadableArchive libJarArchive : libJars) {
                createLibJarBda(libJarArchive, ejbs, libDir);
            }
        }

        return libJarRootBdas;
    }

    private void createLibJarBda(ReadableArchive libJarArchive, Collection ejbs, String libDir ) {
        RootBeanDeploymentArchive rootBda =
            new RootBeanDeploymentArchive(libJarArchive,
                                          ejbs,
                                          context,
                                          libDir + SEPARATOR_CHAR + libJarArchive.getName());
        createLibJarBda(rootBda);
    }

    private void createLibJarBda(RootBeanDeploymentArchive rootLibBda) {
        BeanDeploymentArchive libModuleBda = rootLibBda.getModuleBda();
        BeansXml moduleBeansXml = libModuleBda.getBeansXml();
        if (moduleBeansXml == null || !moduleBeansXml.getBeanDiscoveryMode().equals(BeanDiscoveryMode.NONE)) {
            addBdaToDeploymentBdas(rootLibBda);
            addBdaToDeploymentBdas(libModuleBda);
            if (libJarRootBdas == null) {
                libJarRootBdas = new ArrayList<>();
            }

            for ( RootBeanDeploymentArchive existingLibJarRootBda : libJarRootBdas) {
                rootLibBda.getBeanDeploymentArchives().add( existingLibJarRootBda );
                rootLibBda.getBeanDeploymentArchives().add( existingLibJarRootBda.getModuleBda() );
                rootLibBda.getModuleBda().getBeanDeploymentArchives().add( existingLibJarRootBda );
                rootLibBda.getModuleBda().getBeanDeploymentArchives().add( existingLibJarRootBda.getModuleBda() );

                existingLibJarRootBda.getBeanDeploymentArchives().add( rootLibBda );
                existingLibJarRootBda.getBeanDeploymentArchives().add( rootLibBda.getModuleBda() );
                existingLibJarRootBda.getModuleBda().getBeanDeploymentArchives().add( rootLibBda );
                existingLibJarRootBda.getModuleBda().getBeanDeploymentArchives().add( rootLibBda.getModuleBda() );
            }

            libJarRootBdas.add(rootLibBda);
        }
    }

    private void addBdaToDeploymentBdas( BeanDeploymentArchive bda ) {
        if ( ! beanDeploymentArchives.contains( bda ) ) {
            beanDeploymentArchives.add(bda);
            idToBeanDeploymentArchive.put(bda.getId(), bda);
        }
    }

    // These are application libraries that reside outside of the ear.  They are usually specified by entries
    // in the manifest.
    // to test this put a jar in domains/domain1/lib/applibs and in its manifest make sure it has something like:
    //                           Extension-Name: com.acme.extlib
    // In a war's manifest put in something like:
    //                           Extension-List: MyExtLib
    //                           MyExtLib-Extension-Name: com.acme.extlib
    private void processBdasForAppLibs( ReadableArchive archive, DeploymentContext context ) {
        List libBdas = new ArrayList<>();
        try {
            // each appLib in context.getAppLibs is a URI of the form
            // "file:/glassfish/runtime/trunk/glassfish4/glassfish/domains/domain1/lib/applibs/mylib.jar"
            List appLibs = context.getAppLibs();

            Set installedLibraries = InstalledLibrariesResolver.getInstalledLibraries(archive);
            if ( appLibs != null && !appLibs.isEmpty() && installedLibraries != null && !installedLibraries.isEmpty() ) {
                for ( URI oneAppLib : appLibs ) {
                    for ( String oneInstalledLibrary : installedLibraries ) {
                        if ( oneAppLib.getPath().endsWith( oneInstalledLibrary ) ) {
                            ReadableArchive libArchive = null;
                            try {
                                libArchive = archiveFactory.openArchive(oneAppLib);
                                if ( libArchive.exists( WeldUtils.META_INF_BEANS_XML ) ) {
                                    String bdaId = archive.getName() + "_" + libArchive.getName();
                                    RootBeanDeploymentArchive rootBda =
                                        new RootBeanDeploymentArchive(libArchive,
                                                                      Collections.emptyList(),
                                                                      context,
                                                                      bdaId );
                                    libBdas.add(rootBda);
                                }
                            } finally {
                                if ( libArchive != null ) {
                                    try {
                                        libArchive.close();
                                    } catch ( Exception ignore ) {}
                                }
                            }
                            break;
                        }
                    }
                }
            }
        } catch (URISyntaxException | IOException e) {
            //todo: log error
        }

        for ( RootBeanDeploymentArchive oneBda : libBdas ) {
            createLibJarBda(oneBda );
        }
    }

    protected void addDeployedEjbs( Collection ejbs ) {
        if ( ejbs != null ) {
            deployedEjbs.addAll( ejbs );
        }
    }

    public Collection getDeployedEjbs() {
        return deployedEjbs;
    }

    /**
     * Get a bda for the specified beanClass
     *
     * @param beanClass The beanClass to get the bda for.
     *
     * @return If the beanClass is in the archive represented by the bda
     * then return that bda.  Otherwise if the class loader of the beanClass matches the module class loader
     * of any of the root bdas then return that root bda.  Otherwise return null.
     */
    public BeanDeploymentArchive getBeanDeploymentArchive(Class beanClass) {
        if ( beanClass == null ) {
            return null;
        }

        for ( BeanDeploymentArchive oneBda : beanDeploymentArchives ) {
            BeanDeploymentArchiveImpl beanDeploymentArchiveImpl = (BeanDeploymentArchiveImpl) oneBda;
            if ( beanDeploymentArchiveImpl.getKnownClasses().contains(beanClass.getName()) ) {
                return oneBda;
            }
        }

        // find a root bda
        ClassLoader classLoader = beanClass.getClassLoader();

        RootBeanDeploymentArchive rootBda = findRootBda( classLoader, ejbRootBdas );
        if ( rootBda == null ) {
            rootBda = findRootBda( classLoader, warRootBdas );
            if ( rootBda == null ) {
                rootBda = findRootBda( classLoader, libJarRootBdas );
                if ( rootBda == null ) {
                    rootBda = findRootBda( classLoader, rarRootBdas );
                }
            }
        }

        return rootBda;
    }

    private RootBeanDeploymentArchive findRootBda( ClassLoader classLoader, List rootBdas ) {
        if ( rootBdas == null || classLoader == null ) {
            return null;
        }

        for ( RootBeanDeploymentArchive oneRootBda : rootBdas ) {
            if ( classLoader.equals( oneRootBda.getModuleClassLoaderForBDA() ) ) {
                return oneRootBda;
            }
        }

        return null;
    }

    private void createModuleBda( ReadableArchive archive,
                                  Collection ejbs,
                                  DeploymentContext context,
                                  String moduleName) {
        RootBeanDeploymentArchive rootBda = new RootBeanDeploymentArchive(archive, ejbs, context, moduleName);

            BeanDeploymentArchive moduleBda = rootBda.getModuleBda();
            BeansXml moduleBeansXml = moduleBda.getBeansXml();
            if (moduleBeansXml == null || !moduleBeansXml.getBeanDiscoveryMode().equals(BeanDiscoveryMode.NONE)) {
                addBdaToDeploymentBdas(rootBda);
                addBdaToDeploymentBdas(moduleBda);
                addBeanDeploymentArchives(rootBda);
            }

            // first check if the parent is an ear and if so see if there are app libs defined there.
            if ( ! earContextAppLibBdasProcessed && context instanceof DeploymentContextImpl ) {
                DeploymentContextImpl deploymentContext = ( DeploymentContextImpl ) context;
                DeploymentContext parentContext = deploymentContext.getParentContext();
                if ( parentContext != null ) {
                    processBdasForAppLibs( parentContext.getSource(), parentContext );
                    parentContext.getSource();
                    earContextAppLibBdasProcessed = true;
                }
            }

            // then check the module
            processBdasForAppLibs(archive, context);
    }



    public Iterator getLibJarRootBdas() {
        if ( libJarRootBdas == null ) {
            return null;
        }
        return libJarRootBdas.iterator();
    }

    public Iterator getRarRootBdas() {
        if ( rarRootBdas == null ) {
            return null;
        }
        return rarRootBdas.iterator();
    }

    public String getAppName() {
        return appName;
    }

    public String getContextId() {
        return contextId;
    }

    /**
     * Gets the {@link Types} from the {@link DeploymentContext}'s transient metadata
     *
     * @return The {@link Types} from the {@link DeploymentContext}'s transient metadata
     */
    public Types getTypes() {
        return context.getTransientAppMetaData(Types.class.getName(), Types.class);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy