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

com.sun.enterprise.container.common.impl.ComponentEnvManagerImpl Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2022, 2024 Contributors to the Eclipse Foundation.
 * Copyright (c) 2008, 2020 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2024 Payara Foundation and/or its affiliates
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package com.sun.enterprise.container.common.impl;

import com.sun.enterprise.container.common.spi.EjbNamingReferenceManager;
import com.sun.enterprise.container.common.spi.WebServiceReferenceManager;
import com.sun.enterprise.container.common.spi.util.CallFlowAgent;
import com.sun.enterprise.container.common.spi.util.ComponentEnvManager;
import com.sun.enterprise.deployment.AdministeredObjectDefinitionDescriptor;
import com.sun.enterprise.deployment.Application;
import com.sun.enterprise.deployment.ApplicationClientDescriptor;
import com.sun.enterprise.deployment.ConnectionFactoryDefinitionDescriptor;
import com.sun.enterprise.deployment.ContextServiceDefinitionDescriptor;
import com.sun.enterprise.deployment.DataSourceDefinitionDescriptor;
import com.sun.enterprise.deployment.EjbReferenceDescriptor;
import com.sun.enterprise.deployment.EntityManagerFactoryReferenceDescriptor;
import com.sun.enterprise.deployment.EntityManagerReferenceDescriptor;
import com.sun.enterprise.deployment.EnvironmentProperty;
import com.sun.enterprise.deployment.JMSConnectionFactoryDefinitionDescriptor;
import com.sun.enterprise.deployment.JndiNameEnvironment;
import com.sun.enterprise.deployment.MailSessionDescriptor;
import com.sun.enterprise.deployment.ManagedBeanDescriptor;
import com.sun.enterprise.deployment.ManagedExecutorDefinitionDescriptor;
import com.sun.enterprise.deployment.ManagedScheduledExecutorDefinitionDescriptor;
import com.sun.enterprise.deployment.ManagedThreadFactoryDefinitionDescriptor;
import com.sun.enterprise.deployment.MessageDestinationReferenceDescriptor;
import com.sun.enterprise.deployment.ResourceDescriptor;
import com.sun.enterprise.deployment.ResourceEnvReferenceDescriptor;
import com.sun.enterprise.deployment.ResourceReferenceDescriptor;
import com.sun.enterprise.deployment.ServiceReferenceDescriptor;
import com.sun.enterprise.deployment.annotation.handlers.ConcurrencyResourceDefinition;
import com.sun.enterprise.deployment.types.EntityManagerReference;
import com.sun.enterprise.deployment.util.DOLUtils;
import com.sun.enterprise.naming.spi.NamingObjectFactory;
import com.sun.enterprise.naming.spi.NamingUtils;

import jakarta.inject.Inject;
import jakarta.persistence.EntityManager;
import jakarta.transaction.TransactionManager;
import jakarta.validation.Validation;
import jakarta.validation.ValidationException;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorContext;
import jakarta.validation.ValidatorFactory;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.naming.Context;
import javax.naming.NameNotFoundException;
import javax.naming.NamingException;

import org.glassfish.api.admin.ProcessEnvironment;
import org.glassfish.api.invocation.ApplicationEnvironment;
import org.glassfish.api.invocation.ComponentInvocation;
import org.glassfish.api.invocation.InvocationManager;
import org.glassfish.api.naming.ComponentNamingUtil;
import org.glassfish.api.naming.GlassfishNamingManager;
import org.glassfish.api.naming.JNDIBinding;
import org.glassfish.api.naming.NamingObjectProxy;
import org.glassfish.api.naming.SimpleJndiName;
import org.glassfish.concurro.cdi.ConcurrencyManagedCDIBeans;
import org.glassfish.deployment.common.Descriptor;
import org.glassfish.deployment.common.JavaEEResourceType;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.javaee.services.CommonResourceProxy;
import org.glassfish.javaee.services.JMSCFResourcePMProxy;
import org.glassfish.resourcebase.resources.api.ResourceDeployer;
import org.glassfish.resourcebase.resources.naming.ApplicationScopedResourceBinding;
import org.glassfish.resourcebase.resources.util.ResourceManagerFactory;
import org.jvnet.hk2.annotations.Service;

import static com.sun.appserv.connectors.internal.api.ConnectorsUtil.getPMJndiName;
import static com.sun.enterprise.deployment.util.DOLUtils.getApplicationFromEnv;
import static com.sun.enterprise.deployment.util.DOLUtils.getApplicationName;
import static com.sun.enterprise.deployment.util.DOLUtils.getModuleName;
import static com.sun.enterprise.deployment.util.DOLUtils.getTreatComponentAsModule;
import static java.util.logging.Level.FINE;
import static java.util.logging.Level.SEVERE;
import static org.glassfish.api.naming.SimpleJndiName.JNDI_CTX_JAVA;
import static org.glassfish.api.naming.SimpleJndiName.JNDI_CTX_JAVA_COMPONENT;
import static org.glassfish.api.naming.SimpleJndiName.JNDI_CTX_JAVA_COMPONENT_ENV;
import static org.glassfish.concurro.cdi.ConcurrencyManagedCDIBeans.Type.CONTEXT_SERVICE;
import static org.glassfish.concurro.cdi.ConcurrencyManagedCDIBeans.Type.MANAGED_EXECUTOR_SERVICE;
import static org.glassfish.concurro.cdi.ConcurrencyManagedCDIBeans.Type.MANAGED_SCHEDULED_EXECUTOR_SERVICE;
import static org.glassfish.concurro.cdi.ConcurrencyManagedCDIBeans.Type.MANAGED_THREAD_FACTORY;
import static org.glassfish.deployment.common.JavaEEResourceType.AODD;
import static org.glassfish.deployment.common.JavaEEResourceType.CFD;
import static org.glassfish.deployment.common.JavaEEResourceType.CSDD;
import static org.glassfish.deployment.common.JavaEEResourceType.DSD;
import static org.glassfish.deployment.common.JavaEEResourceType.JMSCFDD;
import static org.glassfish.deployment.common.JavaEEResourceType.JMSDD;
import static org.glassfish.deployment.common.JavaEEResourceType.MEDD;
import static org.glassfish.deployment.common.JavaEEResourceType.MSD;
import static org.glassfish.deployment.common.JavaEEResourceType.MSEDD;
import static org.glassfish.deployment.common.JavaEEResourceType.MTFDD;

@Service
public class ComponentEnvManagerImpl implements ComponentEnvManager {

    private static final Logger LOG = Logger.getLogger(ComponentEnvManagerImpl.class.getName());

    @Inject
    private ServiceLocator locator;

    @Inject
    GlassfishNamingManager namingManager;

    @Inject
    ComponentNamingUtil componentNamingUtil;

    @Inject
    private transient CallFlowAgent callFlowAgent;

    @Inject
    private transient TransactionManager transactionManager;

    @Inject
    private ProcessEnvironment processEnvironment;

    // FIXME: container-common shouldn't depend on EJB stuff, right?
    // this seems like the abstraction design failure.
    @Inject
    private NamingUtils namingUtils;

    @Inject
    private InvocationManager invocationManager;

    private final ConcurrentMap compId2Env = new ConcurrentHashMap<>();

    /**
     * Keep track of number of components using the same component ID so that we can match register
     * calls with unregister calls.
     * EJBs in war files will use the same component ID as the web bundle.
     */
    private static class RefCountJndiNameEnvironment {
        public RefCountJndiNameEnvironment(JndiNameEnvironment env) {
            this.env = env;
            this.refcnt = new AtomicInteger(1);
        }

        public JndiNameEnvironment env;
        public AtomicInteger refcnt;
    }

    public void register(String componentId, JndiNameEnvironment env) {
        LOG.log(Level.FINEST, "register(componentId={0}, env.class={1})", new Object[] {componentId, env.getClass()});
        RefCountJndiNameEnvironment refCountJndiNameEnvironment = compId2Env.putIfAbsent(componentId,
            new RefCountJndiNameEnvironment(env));
        if (refCountJndiNameEnvironment != null) {
            refCountJndiNameEnvironment.refcnt.incrementAndGet();
        }
    }

    public void unregister(String componentId) {
        RefCountJndiNameEnvironment refCountJndiEnvironment = compId2Env.get(componentId);
        if (refCountJndiEnvironment != null && refCountJndiEnvironment.refcnt.decrementAndGet() == 0) {
            compId2Env.remove(componentId);
        }
    }

    @Override
    public JndiNameEnvironment getJndiNameEnvironment(String componentId) {
        LOG.log(Level.FINEST, "getJndiNameEnvironment(componentId={0})", componentId);
        if (componentId == null) {
            return null;
        }
        RefCountJndiNameEnvironment refCountJndiEnvironment = compId2Env.get(componentId);
        return refCountJndiEnvironment == null ? null : refCountJndiEnvironment.env;
    }

    @Override
    public JndiNameEnvironment getCurrentJndiNameEnvironment() {
        ComponentInvocation inv = invocationManager.getCurrentInvocation();
        if (inv == null) {
            return null;
        }
        return getJndiNameEnvironment(inv.componentId);
    }

    @Override
    public String bindToComponentNamespace(final JndiNameEnvironment jndiEnvironment) throws NamingException {
        String componentEnvId = getComponentEnvId(jndiEnvironment);

        Collection bindings = new ArrayList<>();

        // Add all java:comp, java:module, and java:app(except for app clients) dependencies
        // for the specified environment
        addJNDIBindings(jndiEnvironment, ScopeType.COMPONENT, bindings);
        addJNDIBindings(jndiEnvironment, ScopeType.MODULE, bindings);

        if (!(jndiEnvironment instanceof ApplicationClientDescriptor)) {
            addJNDIBindings(jndiEnvironment, ScopeType.APP, bindings);
        }

        if (jndiEnvironment instanceof Application) {
            Application app = (Application) jndiEnvironment;

            // Add any java:app entries defined by any app clients. These must
            // live in the server so they are accessible by other modules in the .ear. Likewise,
            // those same entries will not be registered within the app client JVM itself.
            for (JndiNameEnvironment bundleDescriptor : app.getBundleDescriptors(ApplicationClientDescriptor.class)) {
                addJNDIBindings(bundleDescriptor, ScopeType.APP, bindings);
            }

            namingManager.bindToAppNamespace(getApplicationName(jndiEnvironment), bindings);
        } else {
            // Bind dependencies to the namespace for this component
            namingManager.bindToComponentNamespace(
                    getApplicationName(jndiEnvironment),
                    getModuleName(jndiEnvironment),
                    componentEnvId,
                    getTreatComponentAsModule(jndiEnvironment),
                    bindings);
            // FIXME: Depends on some side effects of preceding calls.
            componentEnvId = getComponentEnvId(jndiEnvironment);
        }

        if (!(jndiEnvironment instanceof ApplicationClientDescriptor)) {
            // Publish any dependencies with java:global names defined by the current env
            // to the global namespace
            Collection globalBindings = new ArrayList<>();
            addJNDIBindings(jndiEnvironment, ScopeType.GLOBAL, globalBindings);

            if (jndiEnvironment instanceof Application) {
                Application app = (Application) jndiEnvironment;

                // Add any java:global entries defined by any app clients. These must
                // live in the server so they are accessible by other modules in the .ear. Likewise,
                // those same entries will not be registered within the app client JVM itself.
                for (JndiNameEnvironment bundleDescriptor : app.getBundleDescriptors(ApplicationClientDescriptor.class)) {
                    addJNDIBindings(bundleDescriptor, ScopeType.GLOBAL, globalBindings);
                }
            }

            for (JNDIBinding globalBinding : globalBindings) {
                namingManager.publishObject(globalBinding.getName(), globalBinding.getValue(), true);
            }
        }

        // If the app contains any application client modules (and the given env isn't
        // an application client) register any java:app dependencies under a well-known
        // internal portion of the global namespace based on the application name. This
        // will allow app client access to application-wide objects within the server.
        Application app = getApplicationFromEnv(jndiEnvironment);
        if (!(jndiEnvironment instanceof ApplicationClientDescriptor)
            && !app.getBundleDescriptors(ApplicationClientDescriptor.class).isEmpty()) {
            for (JNDIBinding binding : bindings) {
                if (dependencyAppliesToScope(binding.getName(), ScopeType.APP)) {
                    namingManager.publishObject(
                        componentNamingUtil.composeInternalGlobalJavaAppName(app.getAppName(), binding.getName()),
                        binding.getValue(),
                        true);
                }
            }
        }

        if (componentEnvId != null) {
            register(componentEnvId, jndiEnvironment);
        }

        return componentEnvId;
    }

    @Override
    public void addToComponentNamespace(JndiNameEnvironment origEnv, Collection envProps,
        Collection resRefs) throws NamingException {
        String componentEnvId = getComponentEnvId(origEnv);

        Collection bindings = new ArrayList<>();

        addEnvironmentProperties(ScopeType.COMPONENT, envProps, bindings);
        addResourceReferences(ScopeType.COMPONENT, resRefs, bindings);

        boolean treatComponentAsModule = getTreatComponentAsModule(origEnv);

        // Bind dependencies to the namespace for this component
        namingManager.bindToComponentNamespace(
                getApplicationName(origEnv),
                getModuleName(origEnv),
                componentEnvId,
                treatComponentAsModule, bindings);
    }

    private String getResourceId(JndiNameEnvironment env, Descriptor desc) {
        if (dependencyAppliesToScope(desc, ScopeType.COMPONENT)) {
            return getApplicationName(env) + "/" + getModuleName(env) + "/" + getComponentEnvId(env);
        }
        if (dependencyAppliesToScope(desc, ScopeType.MODULE)) {
            return getApplicationName(env) + "/" + getModuleName(env);
        }
        if (dependencyAppliesToScope(desc, ScopeType.APP)) {
            return getApplicationName(env);
        }
        return "";
    }

    private void addAllDescriptorBindings(JndiNameEnvironment jndiEnv, ScopeType scope, Collection jndiBindings) {
        Set allDescriptors = new HashSet<>();
        Set dataSourceDefinitions = jndiEnv.getResourceDescriptors(DSD);
        Set messagingConnectionFactoryDefinitions = jndiEnv.getResourceDescriptors(JMSCFDD);
        Set mailSessionDefinitions = jndiEnv.getResourceDescriptors(MSD);
        Set messagingDestinationDefinitions = jndiEnv.getResourceDescriptors(JMSDD);

        Set managedExecutorDefinitions = jndiEnv.getResourceDescriptors(MEDD);
        Set managedScheduledDefinitions = jndiEnv.getResourceDescriptors(MSEDD);
        Set managedThreadfactoryDefintions = jndiEnv.getResourceDescriptors(MTFDD);
        Set contextServiceDefinitions = jndiEnv.getResourceDescriptors(CSDD);

        if (jndiEnv instanceof ApplicationClientDescriptor) {
            LOG.fine("No support for connection-factory in client module.");
        } else {
            Set connectionFactoryDefinitions = jndiEnv.getResourceDescriptors(CFD);
            allDescriptors.addAll(connectionFactoryDefinitions);
        }

        if (jndiEnv instanceof ApplicationClientDescriptor) {
            LOG.fine("No support for administered-object in client module.");
        } else {
            Set administeredObjectDefinitions = jndiEnv.getResourceDescriptors(AODD);
            allDescriptors.addAll(administeredObjectDefinitions);
        }

        allDescriptors.addAll(dataSourceDefinitions);
        allDescriptors.addAll(messagingConnectionFactoryDefinitions);
        allDescriptors.addAll(mailSessionDefinitions);
        allDescriptors.addAll(messagingDestinationDefinitions);

        allDescriptors.addAll(managedExecutorDefinitions);
        allDescriptors.addAll(managedScheduledDefinitions);
        allDescriptors.addAll(managedThreadfactoryDefintions);
        allDescriptors.addAll(contextServiceDefinitions);


        for (ResourceDescriptor descriptor : allDescriptors) {
            if (!dependencyAppliesToScope(descriptor, scope)) {
                continue;
            }

            if (descriptor.getResourceType() == DSD) {
                if (descriptor instanceof DataSourceDefinitionDescriptor && ((DataSourceDefinitionDescriptor) descriptor).isDeployed()) {
                    continue;
                }
            }

            // FIXME: Alert, it modifies the descriptor as a side effect!!! What are consequences?
            descriptor.setResourceId(getResourceId(jndiEnv, descriptor));

            CommonResourceProxy proxy = locator.getService(CommonResourceProxy.class);
            proxy.setDescriptor(descriptor);

            SimpleJndiName logicalJndiName = toLogicalJndiName(descriptor);
            CompEnvBinding envBinding = new CompEnvBinding(logicalJndiName, proxy);
            jndiBindings.add(envBinding);

            // Add another proxy with __PM suffix
            if (descriptor.getResourceType() == JavaEEResourceType.JMSCFDD) {
                CommonResourceProxy jmscfProxy = locator.getService(JMSCFResourcePMProxy.class);
                jmscfProxy.setDescriptor(descriptor);
                CompEnvBinding jmscfEnvBinding = new CompEnvBinding(getPMJndiName(logicalJndiName), jmscfProxy);
                jndiBindings.add(jmscfEnvBinding);
            }
        }

        if (scope == ScopeType.APP) {
            Set concurrencyDescs = new HashSet<>();
            concurrencyDescs.addAll(managedExecutorDefinitions);
            concurrencyDescs.addAll(managedThreadfactoryDefintions);
            concurrencyDescs.addAll(managedScheduledDefinitions);
            concurrencyDescs.addAll(contextServiceDefinitions);
            if (!concurrencyDescs.isEmpty()) {
                registerConcurrencyCDIQualifiers(jndiBindings, concurrencyDescs);
            }
        }
    }

    private void registerConcurrencyCDIQualifiers(Collection jndiBindings, Set concurrencyDescs) {
        ConcurrencyManagedCDIBeans setup = new ConcurrencyManagedCDIBeans();
        for (ResourceDescriptor desc : concurrencyDescs) {
            LOG.log(FINE, () -> "Registering concurrency CDI qualifiers for descriptor: " + desc);
            String jndiName = toLogicalJndiName(desc).toString();
            ConcurrencyResourceDefinition descriptor = (ConcurrencyResourceDefinition) desc;
            Set qualifiers = new HashSet<>(descriptor.getQualifiers());
            // A special value which might occur in XML
            // We don't need it any more.
            qualifiers.remove("");
            if (descriptor instanceof ContextServiceDefinitionDescriptor) {
                setup.addDefinition(CONTEXT_SERVICE, qualifiers, jndiName);
            } else if (descriptor instanceof ManagedExecutorDefinitionDescriptor) {
                setup.addDefinition(MANAGED_EXECUTOR_SERVICE, qualifiers, jndiName);
            } else if (descriptor instanceof ManagedScheduledExecutorDefinitionDescriptor) {
                setup.addDefinition(MANAGED_SCHEDULED_EXECUTOR_SERVICE, qualifiers, jndiName);
            } else if (descriptor instanceof ManagedThreadFactoryDefinitionDescriptor) {
                setup.addDefinition(MANAGED_THREAD_FACTORY, qualifiers, jndiName);
            } else {
                throw new IllegalArgumentException("Unexpected Concurrency type!"
                    + " Expected ContextServiceDefinitionDescriptor, ManagedExecutorDefinitionDescriptor,"
                    + " ManagedScheduledExecutorDefinitionDescriptor, or ManagedThreadFactoryDefinitionDescriptor,"
                    + " got " + descriptor);
            }
        }
        SimpleJndiName jndiName = new SimpleJndiName(ConcurrencyManagedCDIBeans.JDNI_NAME);
        jndiBindings.add(new ApplicationScopedResourceBinding(jndiName, setup));
    }

    private ResourceDeployer getResourceDeployer(Object resource) {
        return locator.getService(ResourceManagerFactory.class).getResourceDeployer(resource);
    }

    @Override
    public void unbindFromComponentNamespace(JndiNameEnvironment JndiEnvironment) throws NamingException {
        // undeploy all descriptors
        undeployAllDescriptors(JndiEnvironment);

        // Unpublish any global entries exported by this environment
        Collection globalBindings = new ArrayList<>();
        addJNDIBindings(JndiEnvironment, ScopeType.GLOBAL, globalBindings);

        for (JNDIBinding globalBinding : globalBindings) {
            namingManager.unpublishObject(globalBinding.getName());
        }

        Application app = getApplicationFromEnv(JndiEnvironment);

        // undeploy data-sources & mail-sessions exposed by app-client descriptors.
        Set appClientDescriptors = app.getBundleDescriptors(ApplicationClientDescriptor.class);
        for (ApplicationClientDescriptor appClientDescriptor : appClientDescriptors) {
            undeployAllDescriptors(appClientDescriptor);
        }

        if (!(JndiEnvironment instanceof ApplicationClientDescriptor) && (app.getBundleDescriptors(ApplicationClientDescriptor.class).size() > 0)) {
            Collection appBindings = new ArrayList<>();
            addJNDIBindings(JndiEnvironment, ScopeType.APP, appBindings);
            for (JNDIBinding appBinding : appBindings) {
                namingManager.unpublishObject(
                    componentNamingUtil.composeInternalGlobalJavaAppName(app.getAppName(), appBinding.getName()));

            }
        }

        if (JndiEnvironment instanceof Application) {
            namingManager.unbindAppObjects(getApplicationName(JndiEnvironment));
        } else {
            // Unbind anything in the component namespace
            String componentEnvId = getComponentEnvId(JndiEnvironment);
            namingManager.unbindComponentObjects(componentEnvId);
            this.unregister(componentEnvId);
        }

    }

    private void undeployAllDescriptors(JndiNameEnvironment env) {
        Set allDescriptors = env.getAllResourcesDescriptors(env.getClass());

        for (ResourceDescriptor descriptor : allDescriptors) {
            switch (descriptor.getResourceType()) {
            case DSD:
                if (descriptor instanceof DataSourceDefinitionDescriptor) {
                    DataSourceDefinitionDescriptor dataSourceDefinitionDescriptor = (DataSourceDefinitionDescriptor) descriptor;
                    if (dataSourceDefinitionDescriptor.isDeployed()) {
                        if (undepoyResource(dataSourceDefinitionDescriptor)) {
                            dataSourceDefinitionDescriptor.setDeployed(false);
                        }
                    }
                }
                break;
            case MSD:
                if (descriptor instanceof MailSessionDescriptor) {
                    MailSessionDescriptor mailSessionDescriptor = (MailSessionDescriptor) descriptor;
                    if (mailSessionDescriptor.isDeployed()) {
                        if (undepoyResource(mailSessionDescriptor)) {
                            mailSessionDescriptor.setDeployed(false);
                        }
                    }
                }
                break;
            case CFD:
                if (descriptor instanceof ConnectionFactoryDefinitionDescriptor) {
                    ConnectionFactoryDefinitionDescriptor connectionFactoryDefinitionDescriptor = (ConnectionFactoryDefinitionDescriptor) descriptor;
                    undepoyResource(connectionFactoryDefinitionDescriptor);
                }
                break;
            case JMSCFDD:
                if (descriptor instanceof JMSConnectionFactoryDefinitionDescriptor) {
                    JMSConnectionFactoryDefinitionDescriptor jmsConnectionFactoryDefinitionDescriptor = (JMSConnectionFactoryDefinitionDescriptor) descriptor;
                    undepoyResource(jmsConnectionFactoryDefinitionDescriptor);
                }
                break;
            case AODD:
                if (descriptor instanceof AdministeredObjectDefinitionDescriptor) {
                    AdministeredObjectDefinitionDescriptor administeredObjectDefinitionDescriptor = (AdministeredObjectDefinitionDescriptor) descriptor;
                    undepoyResource(administeredObjectDefinitionDescriptor);
                }
                break;
            default:
                break;
            }
        }
    }

    private boolean undepoyResource(Descriptor descriptor) {
        try {
            ResourceDeployer deployer = getResourceDeployer(descriptor);
            deployer.undeployResource(descriptor);
            return true;
        } catch (Exception e) {
            LOG.log(Level.WARNING, "Unable to undeploy Descriptor [ " + descriptor.getName() + " ] ", e);
            return false;
        }
    }


    private void addEnvironmentProperties(ScopeType scope, Collection envProps,
        Collection jndiBindings) {
        for (EnvironmentProperty environmentProperty : envProps) {
            if (!dependencyAppliesToScope(environmentProperty, scope)) {
                continue;
            }
            if (environmentProperty.hasContent()) {
                SimpleJndiName name = toLogicalJndiName(environmentProperty);
                final Object value;
                if (environmentProperty.hasLookupName()) {
                    value = namingUtils.createLazyNamingObjectFactory(name, environmentProperty.getLookupName(), true);
                } else if (environmentProperty.getMappedName().isEmpty()) {
                    value = namingUtils.createSimpleNamingObjectFactory(name, environmentProperty.getValueObject(null));
                } else {
                    value = namingUtils.createLazyNamingObjectFactory(name, environmentProperty.getMappedName(), true);
                }
                jndiBindings.add(new CompEnvBinding(name, value));
            }
        }
    }

    private void addResourceReferences(ScopeType scope, Collection resRefs, Collection jndiBindings) {
        for (ResourceReferenceDescriptor resourceRef : resRefs) {
            if (!dependencyAppliesToScope(resourceRef, scope)) {
                continue;
            }
            resourceRef.checkType();

            SimpleJndiName name = toLogicalJndiName(resourceRef);
            SimpleJndiName physicalJndiName = resourceRef.getJndiName();

            // the jndi-name of URL resource can be either the actual URL value,
            // or another jndi-name that can be looked up
            Object value = null;
            if (resourceRef.isURLResource()) {
                if (physicalJndiName.isJavaGlobal() || physicalJndiName.isJavaApp() || physicalJndiName.isJavaModule()
                    || physicalJndiName.isJavaComponent()) {
                    // for jndi-name or lookup-name like "java:module/env/url/testUrl"
                    value = namingUtils.createLazyNamingObjectFactory(name, physicalJndiName, false);
                } else {
                    try {
                        // For jndi-name like "http://localhost:8080/index.html"
                        value = namingUtils.createCloningNamingObjectFactory(name,
                            namingUtils.createSimpleNamingObjectFactory(name, new URL(physicalJndiName.toString())));
                    } catch (MalformedURLException e) {
                        // For jndi-name or lookup-name like "url/testUrl"
                        value = namingUtils.createLazyNamingObjectFactory(name, physicalJndiName, false);
                    }
                }
            } else if (resourceRef.isORB()) {
                // TODO handle non-default ORBs
                value = namingUtils.createLazyNamingObjectFactory(name, physicalJndiName, false);
            } else if (resourceRef.isWebServiceContext()) {
                WebServiceReferenceManager wsRefMgr = locator.getService(WebServiceReferenceManager.class);
                if (wsRefMgr != null) {
                    value = wsRefMgr.getWSContextObject();
                } else {
                    LOG.log(SEVERE, "Cannot find the following class to proceed with @Resource WebServiceContext"
                        + wsRefMgr + "Please confirm if webservices module is installed ");
                }

            } else if (resourceRef.isJDBCResource() || resourceRef.isJMSConnectionFactory()
                || resourceRef.isMailResource() || resourceRef.isResourceConnectionFactory()) {
                value = namingUtils.createLazyInitializationNamingObjectFactory(name, physicalJndiName, false);
            } else {
                value = namingUtils.createLazyNamingObjectFactory(name, physicalJndiName, false);
            }

            jndiBindings.add(new CompEnvBinding(name, value));

        }
    }


    private void addJNDIBindings(final JndiNameEnvironment jndiNameEnvironment, final ScopeType scope, final Collection jndiBindings) {
        // Create objects to be bound for each env dependency. Only add bindings that
        // match the given scope.

        addEnvironmentProperties(scope, jndiNameEnvironment.getEnvironmentProperties(), jndiBindings);

        for (ResourceEnvReferenceDescriptor descriptor : jndiNameEnvironment.getResourceEnvReferenceDescriptors()) {
            if (!dependencyAppliesToScope(descriptor, scope)) {
                continue;
            }

            descriptor.checkType();
            jndiBindings.add(getCompEnvBinding(descriptor));
        }

        addAllDescriptorBindings(jndiNameEnvironment, scope, jndiBindings);

        for (EjbReferenceDescriptor descriptor : jndiNameEnvironment.getEjbReferenceDescriptors()) {
            if (!dependencyAppliesToScope(descriptor, scope)) {
                continue;
            }

            jndiBindings.add(
                new CompEnvBinding(
                        toLogicalJndiName(descriptor),
                        new EjbReferenceProxy(descriptor)));
        }

        for (MessageDestinationReferenceDescriptor descriptor : jndiNameEnvironment.getMessageDestinationReferenceDescriptors()) {
            if (!dependencyAppliesToScope(descriptor, scope)) {
                continue;
            }

            jndiBindings.add(getCompEnvBinding(descriptor));
        }

        addResourceReferences(scope, jndiNameEnvironment.getResourceReferenceDescriptors(), jndiBindings);

        for (EntityManagerFactoryReferenceDescriptor descriptor : jndiNameEnvironment.getEntityManagerFactoryReferenceDescriptors()) {
            if (!dependencyAppliesToScope(descriptor, scope)) {
                continue;
            }

            jndiBindings.add(
                new CompEnvBinding(
                        toLogicalJndiName(descriptor),
                        createFactoryForEntityManagerFactory(descriptor.getUnitName())));
        }

        for (ServiceReferenceDescriptor descriptor : jndiNameEnvironment.getServiceReferenceDescriptors()) {
            if (!dependencyAppliesToScope(descriptor, scope)) {
                continue;
            }

            if (descriptor.getMappedName() != null) {
                descriptor.setName(descriptor.getMappedName().toString());
            }

            jndiBindings.add(
                new CompEnvBinding(
                        toLogicalJndiName(descriptor),
                        new WebServiceRefProxy(descriptor)));
        }

        for (EntityManagerReferenceDescriptor descriptor : jndiNameEnvironment.getEntityManagerReferenceDescriptors()) {
            if (!dependencyAppliesToScope(descriptor, scope)) {
                continue;
            }

            jndiBindings.add(
                new CompEnvBinding(
                        toLogicalJndiName(descriptor),
                        createFactoryForEntityManager(descriptor)));
        }
    }

    public FactoryForEntityManagerWrapper createFactoryForEntityManager(EntityManagerReference descriptor) {
        return new FactoryForEntityManagerWrapper(descriptor, this);
    }

    public FactoryForEntityManagerFactoryWrapper createFactoryForEntityManagerFactory(String unitName) {
        return new FactoryForEntityManagerFactoryWrapper(unitName, invocationManager, this);
    }

    private CompEnvBinding getCompEnvBinding(final ResourceEnvReferenceDescriptor next) {
        final SimpleJndiName name = toLogicalJndiName(next);
        final Object value;
        if (next.isEJBContext()) {
            value = new EjbContextProxy(next.getRefType());
        } else if (next.isValidator()) {
            value = new ValidatorProxy(LOG);
        } else if (next.isValidatorFactory()) {
            value = new ValidatorFactoryProxy(LOG);
        } else if (next.isCDIBeanManager()) {
            value = namingUtils.createLazyNamingObjectFactory(name,
                new SimpleJndiName(JNDI_CTX_JAVA_COMPONENT + "BeanManager"), false);
        } else if (next.isManagedBean()) {
            ManagedBeanDescriptor managedBeanDesc = next.getManagedBeanDescriptor();
            if (processEnvironment.getProcessType().isServer()) {
                value = namingUtils.createLazyNamingObjectFactory(name, next.getJndiName(), false);
            } else {
                value = namingUtils.createLazyNamingObjectFactory(name, managedBeanDesc.getAppJndiName(), false);
            }
        } else {
            // lookup in the InitialContext
            value = new NamingObjectFactory() {
                // It might be mapped to a managed bean, so turn off caching to ensure that a
                // new instance is created each time.
                NamingObjectFactory delegate = namingUtils.createLazyNamingObjectFactory(name, next.getJndiName(), false);

                @Override
                public boolean isCreateResultCacheable() {
                    return false;
                }

                @Override
                public  T create(Context ic) throws NamingException {
                    return delegate.create(ic);
                }
            };
        }

        return new CompEnvBinding(name, value);
    }

    private CompEnvBinding getCompEnvBinding(MessageDestinationReferenceDescriptor messageDestinationRef) {
        final SimpleJndiName name = toLogicalJndiName(messageDestinationRef);
        final SimpleJndiName physicalJndiName;
        if (messageDestinationRef.isLinkedToMessageDestination()) {
            physicalJndiName = messageDestinationRef.getMessageDestination().getJndiName();
        } else {
            physicalJndiName = messageDestinationRef.getJndiName();
        }
        return new CompEnvBinding(name, namingUtils.createLazyNamingObjectFactory(name, physicalJndiName, true));
    }

    private boolean dependencyAppliesToScope(Descriptor descriptor, ScopeType scope) {
        return dependencyAppliesToScope(new SimpleJndiName(descriptor.getName()), scope);
    }

    private boolean dependencyAppliesToScope(SimpleJndiName name, ScopeType scope) {
        LOG.log(Level.FINEST, "dependencyAppliesToScope(name={0}, scope={1})", new Object[] {name, scope});
        switch (scope) {
            case COMPONENT:
                // Env names without an explicit java: prefix default to java:comp
                return name.isJavaComponent() || !name.hasJavaPrefix();
            case MODULE:
                return name.isJavaModule();
            case APP:
                return name.isJavaApp();
            case GLOBAL:
                return name.isJavaGlobal();
            default:
                return false;
        }
    }

    /**
     * Generate the name of an environment dependency in the java: namespace.
     * This is the lookup string used by a component to access the dependency.
     */
    private SimpleJndiName toLogicalJndiName(Descriptor descriptor) {
        // If no java: prefix is specified, default to component scope.
        String rawName = descriptor.getName();
        LOG.log(Level.FINEST, "toLogicalJndiName(descriptor); rawName={0}", rawName);
        return new SimpleJndiName(rawName.startsWith(JNDI_CTX_JAVA) ? rawName : (JNDI_CTX_JAVA_COMPONENT_ENV + rawName));
    }

    /**
     * Generate a unique id name for each EE component.
     */
    @Override
    public String getComponentEnvId(JndiNameEnvironment env) {
        String componentEnvId = DOLUtils.getComponentEnvId(env);
        if (LOG.isLoggable(FINE)) {
            LOG.log(FINE, "ApplicationName={0}, ComponentId={1}",
                new Object[] {getApplicationName(env), componentEnvId});
        }
        return componentEnvId;
    }

    @Override
    public ApplicationEnvironment getCurrentApplicationEnvironment() {
        return invocationManager.peekAppEnvironment();
    }

    public class FactoryForEntityManagerWrapper implements NamingObjectProxy {

        private final EntityManagerReference entityManagerReference;
        private final ComponentEnvManager componentEnvManager;

        FactoryForEntityManagerWrapper(EntityManagerReference entityManagerReference, ComponentEnvManager compEnvMgr) {
            this.entityManagerReference = entityManagerReference;
            this.componentEnvManager = compEnvMgr;
        }

        @SuppressWarnings("unchecked")
        @Override
        public EntityManager create(Context ctx) {
            EntityManagerWrapper entityManagerWrapper =
                new EntityManagerWrapper(
                    transactionManager,
                    invocationManager,
                    componentEnvManager,
                    callFlowAgent);

            entityManagerWrapper.initializeEMWrapper(
                entityManagerReference.getUnitName(),
                entityManagerReference.getPersistenceContextType(),
                entityManagerReference.getSynchronizationType(),
                entityManagerReference.getProperties());

            return entityManagerWrapper;
        }
    }

    private class EjbContextProxy implements NamingObjectProxy {

        private volatile EjbNamingReferenceManager ejbNamingRefManager;
        private final String contextType;

        EjbContextProxy(String contextType) {
            this.contextType = contextType;
        }

        @Override
        public  T create(Context ctx) throws NamingException {
            Object result = null;

            if (ejbNamingRefManager == null) {
                ejbNamingRefManager = locator.getService(EjbNamingReferenceManager.class);
            }

            if (ejbNamingRefManager != null) {
                result = ejbNamingRefManager.getEJBContextObject(contextType);
            }

            if (result == null) {
                throw new NameNotFoundException("Can not resolve EJB context of type " + contextType);
            }

            return (T) result;
        }

    }

    private static class ValidatorProxy implements NamingObjectProxy {

        private volatile ValidatorFactory validatorFactory;
        private volatile Validator validator;
        private final Logger logger;

        private ValidatorProxy(Logger logger) {
            this.logger = logger;
        }

        @Override
        public Validator create(Context ctx) throws NamingException {
            String exceptionMessage = "Can not obtain reference to Validator instance ";

            // Phase 1, obtain a reference to the Validator

            // Create a new Validator instance
            if (validator == null) {

                // no validatorFactory
                if (validatorFactory == null) {
                    ValidatorFactoryProxy factoryProxy = new ValidatorFactoryProxy(logger);
                    validatorFactory = factoryProxy.create(ctx);
                }

                // Use the ValidatorFactory to create a Validator
                if (validatorFactory != null) {
                    ValidatorContext validatorContext = validatorFactory.usingContext();
                    validator = validatorContext.getValidator();
                }
            }

            if (validator == null) {
                throw new NameNotFoundException(exceptionMessage);
            }

            return validator;
        }

    }

    private static class ValidatorFactoryProxy implements NamingObjectProxy {
        private static final String nameForValidatorFactory = JNDI_CTX_JAVA_COMPONENT + "ValidatorFactory";
        private volatile ValidatorFactory validatorFactory;
        private final Logger _logger;

        private ValidatorFactoryProxy(Logger logger) {
            _logger = logger;
        }

        @Override
        public ValidatorFactory create(Context ctx) throws NamingException {

            // create the ValidatorFactory using the spec.
            if (validatorFactory == null) {
                try {
                    validatorFactory = Validation.buildDefaultValidatorFactory();
                } catch (ValidationException e) {
                    _logger.log(Level.WARNING, "Unable to lookup {0}, or build a default Bean Validator Factory: {1}",
                            new Object[] { nameForValidatorFactory, e });
                    NameNotFoundException ne = new NameNotFoundException();
                    ne.initCause(e);
                    throw ne;
                }
            }

            return validatorFactory;
        }
    }

    private class WebServiceRefProxy implements NamingObjectProxy {

        private WebServiceReferenceManager webServiceRefManager;
        private final ServiceReferenceDescriptor serviceRef;

        WebServiceRefProxy(ServiceReferenceDescriptor servRef) {
            this.serviceRef = servRef;
        }

        @Override
        public  T create(Context ctx) throws NamingException {

            final T result;
            webServiceRefManager = locator.getService(WebServiceReferenceManager.class);
            if (webServiceRefManager == null) {
                LOG.log(SEVERE, "Cannot find the WebServiceReferenceManager to proceed with @WebServiceRef."
                    + " Please check if webservices module is installed ");
                result = null;
            } else {
                result = (T) webServiceRefManager.resolveWSReference(serviceRef, ctx);
            }

            if (result == null) {
                throw new NameNotFoundException("Can not resolve webservice context of type " + serviceRef.getName());
            }
            return result;
        }
    }

    private class EjbReferenceProxy implements NamingObjectProxy {

        private final EjbReferenceDescriptor ejbRef;

        private volatile EjbNamingReferenceManager ejbRefMgr;
        private volatile Object cachedResult;
        private Boolean cacheable;

        // Note : V2 had a limited form of ejb-ref caching. It only applied
        // to EJB 2.x Home references where the target lived in the same application
        // as the client. It's not clear how useful that even is and it's of limited
        // value given the behavior is different for EJB 3.x references. For now,
        // all ejb-ref caching is turned off.

        EjbReferenceProxy(EjbReferenceDescriptor ejbRef) {
            this.ejbRef = ejbRef;
        }

        @Override
        public  T create(Context ctx) throws NamingException {

            Object result = null;
            if (ejbRefMgr == null) {
                synchronized (this) {
                    if (ejbRefMgr == null) {
                        ejbRefMgr = locator.getService(EjbNamingReferenceManager.class);
                        cacheable = ejbRefMgr.isEjbReferenceCacheable(ejbRef);
                    }
                }
            }

            if (ejbRefMgr != null) {
                if (cacheable != null && cacheable.booleanValue()) {
                    if (cachedResult == null) {
                        result = cachedResult = ejbRefMgr.resolveEjbReference(ejbRef, ctx);
                    } else {
                        result = cachedResult;
                    }
                } else {
                    result = ejbRefMgr.resolveEjbReference(ejbRef, ctx);
                }
            }

            if (result == null) {
                throw new NameNotFoundException("Can not resolve ejb reference " + ejbRef.getName() + " : " + ejbRef);
            }

            return (T) result;
        }
    }

    private static class CompEnvBinding implements JNDIBinding {

        private final SimpleJndiName name;
        private final Object value;

        CompEnvBinding(SimpleJndiName name, Object value) {
            this.name = name;
            this.value = value;
        }

        @Override
        public SimpleJndiName getName() {
            return name;
        }

        @Override
        public Object getValue() {
            return value;
        }

        @Override
        public String toString() {
            return getClass().getSimpleName() + "[name=" + name + ", value=" + value + "]";
        }
    }

    private enum ScopeType {
        COMPONENT, MODULE, APP, GLOBAL
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy