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

com.sun.ejb.EjbNamingReferenceManagerImpl Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2022 Contributors to the Eclipse Foundation
 * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * 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.ejb;

import com.sun.ejb.containers.EJBContextImpl;
import com.sun.ejb.containers.EJBTimerService;
import com.sun.ejb.containers.EJBTimerServiceWrapper;
import com.sun.enterprise.container.common.spi.EjbNamingReferenceManager;
import com.sun.enterprise.deployment.EjbReferenceDescriptor;
import com.sun.enterprise.util.Utility;

import jakarta.inject.Inject;
import jakarta.inject.Provider;

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

import org.glassfish.api.invocation.ComponentInvocation;
import org.glassfish.api.invocation.InvocationManager;
import org.glassfish.api.naming.SimpleJndiName;
import org.glassfish.enterprise.iiop.api.GlassFishORBHelper;
import org.jvnet.hk2.annotations.Service;
import org.omg.CORBA.ORB;

import static org.glassfish.api.naming.SimpleJndiName.JNDI_CTX_JAVA_APP;
import static org.glassfish.api.naming.SimpleJndiName.JNDI_CTX_JAVA_APP_ENV;
import static org.glassfish.api.naming.SimpleJndiName.JNDI_CTX_JAVA_GLOBAL;

/**
 * @author Mahesh Kannan
 */
@Service
public class EjbNamingReferenceManagerImpl implements EjbNamingReferenceManager {

    @Inject
    InvocationManager invMgr;

    @Inject
    Provider glassFishORBHelperProvider;

    @Override
    public Object resolveEjbReference(EjbReferenceDescriptor ejbRefDesc, Context context)
        throws NamingException {

        Object jndiObj = null;
        boolean resolved = false;


        if( ejbRefDesc.isLocal() ) {
            // local ejb dependencies if there's a lookup string, use that.
            // Otherwise, the ejb will be resolved by EJBUtils.
            if( ejbRefDesc.hasLookupName()) {
                jndiObj = context.lookup(ejbRefDesc.getLookupName().toString());
                resolved = true;
            }
        } else if (!ejbRefDesc.hasJndiName() && ejbRefDesc.hasLookupName()) {
            // For a remote reference, only do a context lookup if there is no
            // jndi name.
            // The thread context class loader usually is the EAR class loader,
            // which is able to load business interfaces.  But if the lookup request
            // originated from appclient, and the ejb-ref is under java:app/env,
            // and it also has a lookup-name, then we need to set the EAR class
            // loader to the thread.  Issue 17376.
            try {
                jndiObj = context.lookup(ejbRefDesc.getLookupName().toString());
            } catch (NamingException e) {
                ClassLoader oldLoader = null;
                try {
                    oldLoader = Utility
                        .setContextClassLoader(ejbRefDesc.getReferringBundleDescriptor().getClassLoader());
                    jndiObj = context.lookup(ejbRefDesc.getLookupName().toString());
                } finally {
                    Utility.setContextClassLoader(oldLoader);
                }
            }
            resolved = true;
        } else if (ejbRefDesc.hasJndiName() && ejbRefDesc.getJndiName().isJavaApp()
            && !ejbRefDesc.getJndiName().hasPrefix(JNDI_CTX_JAVA_APP_ENV)) {

            // This could be an @EJB dependency in an appclient whose target name
            // is a portable java:app ejb name.  Try the global version.  If that
            // doesn't work, the javaURLContext logic should be able to figure it
            // out.
            SimpleJndiName remoteJndiName = ejbRefDesc.getJndiName();

            String appName = (String) context.lookup(JNDI_CTX_JAVA_APP + "AppName");
            String globalLookup = remoteJndiName.changePrefix(JNDI_CTX_JAVA_GLOBAL + appName + '/').toString();
            jndiObj = context.lookup(globalLookup);
            resolved = true;
        } else {

            // Get actual jndi-name from ejb module.
            SimpleJndiName remoteJndiName = EJBUtils.getRemoteEjbJndiName(ejbRefDesc);

            // We could be resolving an ejb-ref as part of a remote lookup thread.  In that
            // case the context class loader won't be set appropriately on the thread
            // being used to process the remote naming request.   We can't just always
            // set the context class loader to the class loader of the application module
            // that defined the ejb reference.  That would cause ClassCastExceptions
            // when the returned object is assigned within a cross-application intra-server
            // lookup. So, just try to lookup the interface associated with the ejb-ref
            // using the context class loader.  If that doesn't work, explicitly use the
            // defining application's class loader.

            ClassLoader origClassLoader = Utility.getClassLoader();
            boolean setCL = false;

            try {

                try {

                    String refInterface = ejbRefDesc.isEJB30ClientView() ?
                       ejbRefDesc.getEjbInterface() : ejbRefDesc.getHomeClassName();
                    origClassLoader.loadClass(refInterface);

                } catch(ClassNotFoundException e) {

                     ClassLoader referringBundleClassLoader =
                             ejbRefDesc.getReferringBundleDescriptor().getClassLoader();
                     Utility.setContextClassLoader(referringBundleClassLoader);
                     setCL = true;

                }

                /* For remote ejb refs, first lookup the target remote object
                 * and pass it to the next stage of ejb ref resolution.
                 * If the string is a "corbaname:...." URL
                 * the lookup happens thru the corbanameURL context,
                 * else it happens thru the context provided by the NamingManager.
                 *
                 * NOTE : we might need some additional logic to handle cross-server
                 * MEJB resolution for cluster support post V3 FCS.
                 */
                if (remoteJndiName.hasCorbaPrefix()) {
                    GlassFishORBHelper orbHelper = glassFishORBHelperProvider.get();
                    ORB orb = orbHelper.getORB();
                    jndiObj = orb.string_to_object(remoteJndiName.toString());
                } else {
                    jndiObj = context.lookup(remoteJndiName.toString());
                }

            } catch(Exception e) {
                // Important to make the real underlying lookup name part of the exception.
                NamingException ne = new NamingException("Exception resolving Ejb for '" +
                    ejbRefDesc + "' .  Actual (possibly internal) Remote JNDI name used for lookup is '" +
                    remoteJndiName + "'");
                ne.initCause(e);
                throw ne;
            } finally {
                if( setCL ) {
                    Utility.setContextClassLoader(origClassLoader);
                }
            }
        }

        return resolved ? jndiObj : EJBUtils.resolveEjbRefObject(ejbRefDesc, jndiObj);
    }

    @Override
    public boolean isEjbReferenceCacheable(EjbReferenceDescriptor ejbRefDesc) {
        // Ejb-ref is only eligible for caching if it refers to the legacy
        // Home view and it is resolved to an ejb within the same application.
        return ( (!ejbRefDesc.isEJB30ClientView()) &&
                 (ejbRefDesc.getEjbDescriptor() != null) );

        // caching not enabled.
        //return false;
    }


    @Override
    public Object getEJBContextObject(String contextType) {

        ComponentInvocation currentInv = invMgr.getCurrentInvocation();

        if(currentInv == null) {
            throw new IllegalStateException("no current invocation");
        } else if (currentInv.getInvocationType() !=
                   ComponentInvocation.ComponentInvocationType.EJB_INVOCATION) {
            throw new IllegalStateException
                ("Illegal invocation type for EJB Context : "
                 + currentInv.getInvocationType());
        }

        EjbInvocation ejbInv = (EjbInvocation) currentInv;

        Object returnObject = ejbInv.context;

        if (contextType.equals("jakarta.ejb.TimerService")) {
            if (EJBTimerService.getEJBTimerService() == null) {
                throw new IllegalStateException("EJB Timer Service not available");
            }
            returnObject = new EJBTimerServiceWrapper(EJBTimerService.getEJBTimerService(),
                (EJBContextImpl) ejbInv.context);
        }
        return returnObject;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy