Package org.glassfish.enterprise.iiop.impl

Source Code of org.glassfish.enterprise.iiop.impl.POARemoteReferenceFactory

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2011 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.
*/

package org.glassfish.enterprise.iiop.impl;


import javax.ejb.NoSuchObjectLocalException;

import java.rmi.Remote;

import java.security.AccessController ;
import java.security.PrivilegedAction ;

import org.omg.CORBA.portable.Delegate;

import org.glassfish.enterprise.iiop.api.RemoteReferenceFactory;

import org.glassfish.enterprise.iiop.spi.EjbContainerFacade;

import org.omg.PortableServer.POA ;
import org.omg.PortableServer.Servant ;
import org.omg.PortableServer.ServantLocator ;
import org.omg.PortableServer.ServantLocatorPackage.CookieHolder ;

import com.sun.logging.LogDomains;

import com.sun.enterprise.deployment.EjbDescriptor;

import com.sun.enterprise.deployment.runtime.IASEjbExtraDescriptors;

// TODO Only needed for checkpointing
// import com.sun.ejb.base.sfsb.util.EJBServerConfigLookup;

import com.sun.corba.ee.spi.extension.ServantCachingPolicy;
import com.sun.corba.ee.spi.extension.ZeroPortPolicy;
import com.sun.corba.ee.spi.extension.CopyObjectPolicy;

import com.sun.corba.ee.spi.presentation.rmi.PresentationManager ;

import com.sun.corba.ee.spi.presentation.rmi.StubAdapter;
import com.sun.corba.ee.spi.oa.rfm.ReferenceFactory ;
import com.sun.corba.ee.spi.oa.rfm.ReferenceFactoryManager ;

import com.sun.corba.ee.spi.orbutil.ORBConstants;
import com.sun.corba.ee.org.omg.CORBA.SUNVMCID;
import com.sun.corba.ee.spi.ior.IOR;
import com.sun.corba.ee.spi.ior.ObjectKey;
import com.sun.corba.ee.spi.ior.TaggedProfile;
import com.sun.corba.ee.spi.orb.ORB;

import com.sun.enterprise.util.Utility;

import com.sun.corba.ee.spi.orbutil.codegen.Wrapper ;
import java.util.List;
import java.util.ArrayList;
import java.util.logging.Level;
import javax.rmi.CORBA.Tie;
import javax.rmi.CORBA.Util;
import org.omg.CORBA.CompletionStatus;
import org.omg.CORBA.OBJECT_NOT_EXIST;
import org.omg.CORBA.Policy;

/**
* This class implements the RemoteReferenceFactory interface for the
* RMI/IIOP ORB with POA (Portable Object Adapter).
* There is one instance of the POARemoteReferenceFactory for each
* EJB type.
*
* It also implements the preinvoke/postinvoke APIs in the
* POA's ServantLocator interface, which are called before/after
* every invocation (local or remote).
* It creates a RMI-IIOP-POA object reference (a stub) for every EJBObject
* and EJBHome in the EJB container.
*
* @author Kenneth Saks
*/

public final class POARemoteReferenceFactory extends org.omg.CORBA.LocalObject
      implements RemoteReferenceFactory, ServantLocator
{
    static final int PASS_BY_VALUE_ID = 0;
    static final int PASS_BY_REFERENCE_ID = 1;

    static final int OTS_POLICY_TYPE = SUNVMCID.value + 123;
    static final int CSIv2_POLICY_TYPE = SUNVMCID.value + 124;
    static final int REQUEST_DISPATCH_POLICY_TYPE = SUNVMCID.value + 125;
    static final int SFSB_VERSION_POLICY_TYPE = SUNVMCID.value + 126;
   
    private static final java.util.logging.Logger logger =
    java.util.logging.Logger.getLogger(LogDomains.CORBA_LOGGER);
    private static final int GET_TIE_EXCEPTION_CODE = 9999;

    private EjbContainerFacade container;
    private EjbDescriptor ejbDescriptor;
    private ClassLoader appClassLoader;

    private ORB orb;
    private POAProtocolMgr protocolMgr;
    private PresentationManager presentationMgr;

    private ReferenceFactory ejbHomeReferenceFactory ;
    private PresentationManager.StubFactory ejbHomeStubFactory;
    private String ejbHomeRepositoryId;

    private ReferenceFactory ejbObjectReferenceFactory ;
    private PresentationManager.StubFactory ejbObjectStubFactory;
    private String ejbObjectRepositoryId;

    private String remoteBusinessIntf;
   
    // true if remote home view.  false if remote business view.
    // Used when getting target object for an invocation.
    private boolean isRemoteHomeView;

    private String poaId_EJBHome;
    private String poaId_EJBObject;

    // The EJB key format with field-name(size in bytes):
    // -----------------------------------------
    // | EJB ID(8) | INSTANCEKEY | INSTANCEKEY |
    // |           | LENGTH(4)   |   (unknown) |
    // -----------------------------------------
    // The following are the offsets for the fields in the EJB key.
    static final int EJBID_OFFSET = 0;
    private static final int INSTANCEKEYLEN_OFFSET = 8;
    private static final int INSTANCEKEY_OFFSET = 12;

    POARemoteReferenceFactory(EjbContainerFacade container, POAProtocolMgr protocolMgr,
            ORB orb, boolean remoteHomeView, String id) {
   
        this.protocolMgr = protocolMgr;
        this.orb = orb;
        this.poaId_EJBHome   = id + "-EJBHome";
        this.poaId_EJBObject = id + "-EJBObject";
        this.presentationMgr = orb.getPresentationManager();
        this.container = container;
        this.ejbDescriptor = container.getEjbDescriptor();
        this.isRemoteHomeView = remoteHomeView;

        appClassLoader = container.getClassLoader();

        // NOTE: ReferenceFactory creation happens in setRepositoryIds.
    }

    @Override
    public int getCSIv2PolicyType() {
        return CSIv2_POLICY_TYPE;
    }

    private String getRepositoryId(Class c) throws Exception {

        // Using PresentationManager to get repository ID will always work,
        // independent of whether we have generated static RMI-IIOP stubs.

        PresentationManager.ClassData cData = presentationMgr.getClassData(c);
        String[] typeIds = cData.getTypeIds()

      if (logger.isLoggable(Level.FINE)) {
          logger.log(Level.FINE, ".getRepositoryId: {0}", typeIds[0]);
      }

        // Repository id is always 1st element in array.
        return typeIds[0];
    }

    @Override
    public void setRepositoryIds(Class homeIntf, Class remoteIntf)
    {
        PresentationManager.StubFactoryFactory sff =
            ORB.getStubFactoryFactory();

        // Home
        ejbHomeStubFactory =
            sff.createStubFactory( homeIntf.getName(), false,
                                   "", null, appClassLoader);
        String[] ejbHomeTypeIds = ejbHomeStubFactory.getTypeIds();
        ejbHomeRepositoryId = ejbHomeTypeIds[0];

        ejbObjectStubFactory = sff.createStubFactory
            ( remoteIntf.getName(), false, "", null, appClassLoader);

        String[] ejbObjectTypeIds = ejbObjectStubFactory.getTypeIds();

        ejbObjectRepositoryId = ejbObjectTypeIds[0];

        if (logger.isLoggable(Level.FINE)) {
            logger.log(Level.FINE, ".setRepositoryIds:" + " " + "{0} {1}",
                new Object[]{ejbHomeRepositoryId, ejbObjectRepositoryId});
        }

        try {

            ejbHomeReferenceFactory
                    = createReferenceFactory(poaId_EJBHome, ejbHomeRepositoryId);
            ejbObjectReferenceFactory
                    = createReferenceFactory(poaId_EJBObject, ejbObjectRepositoryId);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        if( !isRemoteHomeView ) {
            remoteBusinessIntf = remoteIntf.getName();
        }
           
    }

    @Override
    public void cleanupClass(Class clazz) {

        try {
            presentationMgr.flushClass(clazz);
        } catch(Exception e) {
            logger.log(Level.FINE, "cleanupClass error", e);
        }
    }

    private ReferenceFactory createReferenceFactory(String poaId, String repoid ) throws Exception {
        try {
            if (logger.isLoggable(Level.FINE)) {
                logger.log(Level.FINE, ".createReferenceFactory->: {0} {1}",
                    new Object[]{poaId, repoid});
      }

      ReferenceFactoryManager rfm =
          (ReferenceFactoryManager) orb.resolve_initial_references(
                    ORBConstants.REFERENCE_FACTORY_MANAGER) ;

      List<Policy> policies = new ArrayList<Policy>();

      // Servant caching for local RMI-IIOP invocation performance
            policies.add(ServantCachingPolicy.getPolicy());

      policies.add(new OTSPolicyImpl());

      if (logger.isLoggable(Level.FINE)) {
          logger.log(Level.FINE, ".createReferenceFactory: {0} {1}: {2}",
                    new Object[]{poaId, repoid, ejbDescriptor});

      }

      // CSIv2 Policy
      policies.add(new CSIv2Policy(ejbDescriptor));

      IASEjbExtraDescriptors extraDesc
          = ejbDescriptor.getIASEjbExtraDescriptors();
      String threadPoolName = extraDesc.getUseThreadPoolId();
      int threadPoolNumericID = 0;
      boolean usePassByReference = extraDesc.getPassByReference();

      if (usePassByReference) {
          policies.add(new CopyObjectPolicy(PASS_BY_REFERENCE_ID));
      }

            /** TODO get thread pool name from config
      if (threadPoolName != null) {
          ThreadPoolManager threadPoolManager
            = S1ASThreadPoolManager.getThreadPoolManager();
          try {
            threadPoolNumericID = threadPoolManager.getThreadPoolNumericId(
            threadPoolName);
            policies.add(new RequestPartitioningPolicy(threadPoolNumericID));
          } catch (Exception ex) {
                logger.log(Level.WARNING, "Not using threadpool-request-partitioning...", ex);
          }
      }
            **/

            /** TODO
            logger.log(Level.INFO, "POARemoteRefFactory checking if SFSBVersionPolicy need to be added");
            EJBServerConfigLookup ejbConfigLookup =
                new EJBServerConfigLookup(ejbDescriptor);
            boolean addSFSBVersionPolicy = EJBServerConfigLookup.needToAddSFSBVersionInterceptors();
            logger.log(Level.INFO, "POARemoteRefFactory addSFSBVersionPolicy? " + addSFSBVersionPolicy);
            if (addSFSBVersionPolicy) {
                if (container instanceof StatefulSessionContainer) {
                    StatefulSessionContainer sfsbCon = (StatefulSessionContainer) container;
                    if (sfsbCon.isHAEnabled()) {
                        policies.add(new SFSBVersionPolicy(ejbDescriptor.getUniqueId()));
                    }
                }
            }
            **/

            if (logger.isLoggable(Level.FINE)) {
                String jndiName = ejbDescriptor.getJndiName();
                logger.log(Level.FINE,
                    "Using Thread-Pool: [{0} ==> {1}] for jndi name: {2}",
                    new Object[]{threadPoolName, threadPoolNumericID, jndiName});
                logger.log(Level.FINE, "Pass by reference: [{0}] for jndi name: {1}",
                    new Object[]{usePassByReference, usePassByReference});
            }

      // DisableClearTextIIOP policy which sets IIOP Profile port to 0
      // if EJB allows only SSL invocations
      if ( ejbDescriptor.allMechanismsRequireSSL() ) {
          if (logger.isLoggable(Level.FINE)) {
                    logger.log(Level.WARNING,
                        ".createReferenceFactory: {0} {1}: adding ZeroPortPolicy",
                        new Object[]{poaId, repoid});
          }
          policies.add(ZeroPortPolicy.getPolicy());
      }


      if (logger.isLoggable(Level.FINE)) {
          logger.log(Level.FINE,
                    ".createReferenceFactory: {0} {1}: policies: {2}",
                    new Object[]{poaId, repoid, policies});
      }

      ReferenceFactory rf = rfm.create( poaId, repoid, policies, this ) ;
      return rf ;
        } finally {
      if (logger.isLoggable(Level.FINE)) {
          logger.log(Level.WARNING,
                    ".createReferenceFactory<-: {0} {1}",
                    new Object[]{poaId, repoid});
      }
        }
    }


    @Override
    public java.rmi.Remote createRemoteReference(byte[] instanceKey)
    {
      return createRef(instanceKey, ejbObjectReferenceFactory,
          ejbObjectStubFactory, ejbObjectRepositoryId );
    }


    @Override
    public Remote createHomeReference(byte[] homeKey)
    {
      return createRef(homeKey, ejbHomeReferenceFactory,
          ejbHomeStubFactory, ejbHomeRepositoryId ) ;
    }

    private void setClassLoader() {
        ClassLoader cl ;
        SecurityManager sman = System.getSecurityManager() ;
        if (sman == null) {
            cl = this.getClass().getClassLoader() ;
        } else {
            cl = AccessController.doPrivileged(
                new PrivilegedAction<ClassLoader>() {
                    @Override
                    public ClassLoader run() {
                        return this.getClass().getClassLoader() ;
                    }
                }
            ) ;
        }

        Wrapper._setClassLoader( cl ) ;
    }

    private Remote createRef(byte[] instanceKey, ReferenceFactory rf,
        PresentationManager.StubFactory stubFactory, String repoid )
    {
        try {
            PresentationManager.StubFactory stubFact = stubFactory;
            org.omg.CORBA.Object ref = _createRef(rf, instanceKey,repoid);
               
            // Set the ClassLoader to the ClassLoader for this class,
            // which is loaded by the OSGi bundle ClassLoader for the
            // orb-iiop bundle, which depends on (among others) the
            // glassfish-corba-codegen bundle, which contains the
            // CodegenProxyStub class needed inside the makeStub call.
            setClassLoader() ;

            org.omg.CORBA.Object stub = stubFact.makeStub();
            Delegate delegate = StubAdapter.getDelegate(ref);
            StubAdapter.setDelegate(stub, delegate);

            return (Remote) stub;

        } catch(Exception e) {
            logger.log(Level.SEVERE, "iiop.createreference_exception",
                       e.toString());

            throw new RuntimeException("Unable to create reference ",e);
        }
    }

    // NOTE: The repoid is only needed for logging.
    private org.omg.CORBA.Object _createRef( ReferenceFactory rf,
      byte[] instanceKey, String repoid ) throws Exception {

        if ( logger.isLoggable(Level.FINE) ) {
            logger.log(Level.FINE,
                "\t\tIn POARemoteReferenceFactory._createRef, repositoryId = {0}",
                repoid);
        }

        // Create the ejbKey using EJB's unique id + instanceKey
        byte[] ejbKey =  createEJBKey(ejbDescriptor.getUniqueId(),
                                     instanceKey);
       
        org.omg.CORBA.Object obj = rf.createReference( ejbKey ) ;

        return obj;
    }
  
    private byte[] createEJBKey(long ejbId, byte[] instanceKey)
    {
        byte[] ejbkey = new byte[INSTANCEKEY_OFFSET+instanceKey.length];

        Utility.longToBytes(ejbId, ejbkey, EJBID_OFFSET);
        Utility.intToBytes(instanceKey.length, ejbkey, INSTANCEKEYLEN_OFFSET);
        System.arraycopy(instanceKey, 0, ejbkey,
            INSTANCEKEY_OFFSET, instanceKey.length);
        return ejbkey;
    }

    /**
     * Disconnect an EJBObject or EJBHome from the ORB.
     */
    @Override
    public void destroyReference(Remote remoteRef, Remote remoteObj)
    {
        // Note: the POAs have the NON_RETAIN policy so they dont maintain
        // any state for objects. We only need to unexport the object from
        // the RMI/IIOP machinery.
        // The following call also does tie.deactivate() for the remoteObj's tie
        try {
            Util.unexportObject(remoteObj);
        } catch ( RuntimeException ex ) {
            // A bug in Util.unexportObject causes this exception
            // Ignore it.
        } catch ( java.lang.Exception nsoe ){
            // eat it and ignore it.
        }
    }

    /**
     * This is the implementation of ServantLocator.preinvoke()
     * It is called from the POA before every remote invocation.
     * Return a POA Servant (which is the RMI/IIOP Tie for EJBObject/EJBHome).
     * @param ejbKey
     * @param cookieHolder
     */
    @Override
    public Servant preinvoke(byte[] ejbKey, POA adapter, String operation,
                                CookieHolder cookieHolder)
                throws org.omg.PortableServer.ForwardRequest
    {
        if (logger.isLoggable(Level.FINE)) {
            logger.log(Level.FINE, "In preinvoke for operation:{0}", operation);
        }

        // get instance key
        int keyLen = Utility.bytesToInt(ejbKey, INSTANCEKEYLEN_OFFSET);
        byte[] instanceKey = new byte[keyLen];
        System.arraycopy(ejbKey, INSTANCEKEY_OFFSET, instanceKey, 0, keyLen);

        Servant servant = null;
        try {
            while ( servant == null ) {
                // get the EJBObject / EJBHome
                Remote targetObj =
                container.getTargetObject(instanceKey,
                    (isRemoteHomeView ? null : remoteBusinessIntf));

                // This could be null in rare cases for sfsbs and entity
                // beans.  It would be preferable to push the retry logic
                // within the sfsb container and entity container
                // implementations of getTargetObject, but for now let's keep
                // the looping logic the same as it has always been.
                if( targetObj != null ) {
                    // get the Tie which is the POA Servant
                    //fix for bug 6484935
                    @SuppressWarnings("unchecked")
                    Tie tie = (Tie)AccessController.doPrivileged(
                        new PrivilegedAction() {
                        @Override
                            public Tie run()  {
                                return presentationMgr.getTie();
                        }
                    });

                    tie.setTarget(targetObj);
                    servant = (Servant) tie;
                }
            }
        } catch (NoSuchObjectLocalException e) {
            logger.log(Level.SEVERE,"iiop.gettie_exception", e);
            throw new OBJECT_NOT_EXIST( GET_TIE_EXCEPTION_CODE,
          CompletionStatus.COMPLETED_NO);
        } catch (RuntimeException e) {
            logger.log(Level.SEVERE,"iiop.runtime_exception", e);
          throw e;
      }

        return servant;
    }

    @Override
    public void postinvoke(byte[] ejbKey, POA adapter, String operation,
                            java.lang.Object cookie, Servant servant)
    {
        Remote target = null;
        if ( servant != null ) {
            target = ((Tie)servant).getTarget();
        }

        // Always release, since that restores previous context class loader.
        container.releaseTargetObject(target);
    }


    @Override
    public void destroy() {
        try {
            ejbHomeReferenceFactory.destroy() ;
            ejbObjectReferenceFactory.destroy() ;
            ejbHomeReferenceFactory = null ;
            ejbObjectReferenceFactory = null ;

            container = null;
            ejbDescriptor = null;

            orb = null;
            protocolMgr = null;

        } catch (Throwable th) {
            logger.log(Level.SEVERE, "Exception during "
                       + "POARemoteRefFactory::destroy()", th);
        }
    }

    @Override
    public boolean hasSameContainerID(org.omg.CORBA.Object obj)
  throws Exception
    {
  boolean result = false;
  try {
      IOR ior = (orb).getIOR(obj, false);
      java.util.Iterator iter = ior.iterator();

      byte[] oid = null;
      if (iter.hasNext()) {
                TaggedProfile profile = (TaggedProfile) iter.next();
                ObjectKey objKey = profile.getObjectKey();
                oid = objKey.getId().getId();
      }

      if ((oid != null) && (oid.length > INSTANCEKEY_OFFSET)) {
                long cid = Utility.bytesToLong(oid, EJBID_OFFSET);
                // To be really sure that is indeed a ref generated
                //  by our container we do the following checks
                int keyLen = Utility.bytesToInt(oid, INSTANCEKEYLEN_OFFSET);
                if (oid.length == keyLen + INSTANCEKEY_OFFSET) {
                    result = (cid == ejbDescriptor.getUniqueId() );
                }
                if (logger.isLoggable(Level.FINE)) {
                    StringBuilder sbuf = new StringBuilder();
                    sbuf.append("hasSameContainerID() result: ").append(result)
                        .append("; because ==> oid.length: ").append(oid.length)
                        .append("; instance-key-length: ").append(keyLen)
                        .append("; expected oid.length: ")
                        .append(keyLen).append("+").append(INSTANCEKEY_OFFSET)
                        .append("; myContainrID: ")
                        .append(ejbDescriptor.getUniqueId())
                        .append("; obj.containerID: ")
                        .append(cid);
                    logger.log(Level.FINE, sbuf.toString());
                }
      } else {
                if (logger.isLoggable(Level.FINE)) {
                    if (oid == null) {
                        logger.log(Level.FINE,
                            "hasSameContainerID() failed because oid=null");
                    } else {
                        logger.log(Level.FINE,
                            "hasSameContainerID() failed because oid.length= "
                            + "{0}; but INSTANCE_KEY_OFFSET= {1}",
                            new Object[]{oid.length, INSTANCEKEY_OFFSET});
                    }
                }
      }
  } catch (Exception ex) {
      logger.log(Level.FINE, "Exception while checking for same containerID", ex);
      throw ex;
  }

  return result;
    }
}
TOP

Related Classes of org.glassfish.enterprise.iiop.impl.POARemoteReferenceFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.