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

com.sun.ejb.base.io.EJBObjectOutputStreamHandler Maven / Gradle / Ivy

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2012 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-2018] [Payara Foundation and/or its affiliates]

package com.sun.ejb.base.io;

import com.sun.ejb.containers.BaseContainer;
import com.sun.ejb.EJBUtils;
import com.sun.ejb.containers.EjbContainerUtilImpl;
import com.sun.ejb.containers.RemoteBusinessWrapperBase;
import com.sun.enterprise.container.common.spi.util.JavaEEIOUtils;
import com.sun.logging.LogDomains;


import com.sun.enterprise.util.Utility;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.io.IOException;
import java.io.Serializable;
import java.util.Optional;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.glassfish.enterprise.iiop.api.ProtocolManager;
import org.glassfish.enterprise.iiop.api.GlassFishORBHelper;
import org.glassfish.internal.api.Globals;
import org.glassfish.api.naming.GlassfishNamingManager;

import com.sun.enterprise.container.common.spi.util.GlassFishOutputStreamHandler;
import com.sun.enterprise.container.common.spi.util.SerializableObjectFactory;

/**
 * A class that is used to passivate SFSB conversational state
 *
 * @author Mahesh Kannan
 */
public class EJBObjectOutputStreamHandler
    implements GlassFishOutputStreamHandler
{
    static JavaEEIOUtils _javaEEIOUtils;

    protected static final Logger _ejbLogger =
            LogDomains.getLogger(EJBObjectOutputStreamHandler.class, LogDomains.EJB_LOGGER);

    static final int EJBID_OFFSET = 0;
    static final int INSTANCEKEYLEN_OFFSET = 8;
    static final int INSTANCEKEY_OFFSET = 12;

    private static final byte HOME_KEY = (byte)0xff;

    //Ugly,
    public static final void setJavaEEIOUtils(JavaEEIOUtils javaEEIOUtils) {
        _javaEEIOUtils = javaEEIOUtils;
    }

    /**
     * This code is needed to serialize non-Serializable objects that
     * can be part of a bean's state. See EJB2.0 section 7.4.1.
     */
    public Object replaceObject(Object obj)
            throws IOException {
        Object result = obj;
        if (obj instanceof RemoteBusinessWrapperBase) {
            result = getRemoteBusinessObjectFactory
                    ((RemoteBusinessWrapperBase) obj);
        } else {
            // Until we've identified a remote object, we can't assume the orb is
            // available in the container.  If the orb is not present, this will be null.
            Optional protocolManager = getProtocolManager();
            if (protocolManager.isPresent() &&
                protocolManager.get().isStub(obj) &&
                protocolManager.get().isLocal(obj))
            {
                org.omg.CORBA.Object target = (org.omg.CORBA.Object) obj;
                // If we're here, it's always for the 2.x RemoteHome view.
                // There is no remote business wrapper class.
                result = getSerializableEJBReference(target, protocolManager.get(), null);
            }
        }

        return result;
    }


    /**
     * Do all ProtocolManager access lazily and only request orb if it has already been
     * initialized so that code doesn't make the assumption that an orb is available in
     * this runtime.
     */
    private Optional getProtocolManager() {
	    GlassFishORBHelper orbHelper = Globals.getDefaultHabitat().getService(GlassFishORBHelper.class);
	    return orbHelper.isORBInitialized() ? Optional.of(orbHelper.getProtocolManager()) : Optional.empty();
    }

    private Serializable getRemoteBusinessObjectFactory
        (RemoteBusinessWrapperBase remoteBusinessWrapper)
        throws IOException {
        // Create a serializable object with the remote delegate and
        // the name of the client wrapper class.
        org.omg.CORBA.Object target = (org.omg.CORBA.Object)
            remoteBusinessWrapper.getStub();
        return getSerializableEJBReference(
                target,
                getProtocolManager().orElse(null),
                remoteBusinessWrapper.getBusinessInterfaceName()
        );
    }

    private Serializable getSerializableEJBReference(org.omg.CORBA.Object obj,
						     ProtocolManager protocolMgr,
                             String remoteBusinessInterface)
	throws IOException
    {
        Serializable result = (Serializable) obj;
        if (protocolMgr != null) {
            try {
                byte[] oid = protocolMgr.getObjectID(obj);
                if ((oid != null) && (oid.length > INSTANCEKEY_OFFSET)) {
                    long containerId = Utility.bytesToLong(oid, EJBID_OFFSET);
                    //To be really sure that is indeed a ref generated
                    //  by our container we do the following checks
                    int keyLength = Utility.bytesToInt(oid, INSTANCEKEYLEN_OFFSET);
                    if (oid.length == keyLength + INSTANCEKEY_OFFSET) {
                        boolean isHomeReference =
                            ((keyLength == 1) && (oid[INSTANCEKEY_OFFSET] == HOME_KEY));
                        if (isHomeReference) {
                            result = new SerializableS1ASEJBHomeReference(containerId);
                        } else {
                            SerializableS1ASEJBObjectReference serRef =
                                new SerializableS1ASEJBObjectReference(containerId,
                                oid, keyLength, remoteBusinessInterface);
                            result = serRef;
                            /* TODO
                            if (serRef.isHAEnabled()) {
                                SimpleKeyGenerator gen = new SimpleKeyGenerator();
                                Object key = gen.byteArrayToKey(oid, INSTANCEKEY_OFFSET, 20);
                                long version = SFSBClientVersionManager.getClientVersion(
                                        containerId, key);
                                serRef.setSFSBClientVersion(key, version);
                            } */
                        }
                    }
                }
            } catch (Exception ex) {
                _ejbLogger.log(Level.WARNING, "Exception while getting serializable object", ex);
                IOException ioEx = new IOException("Exception during extraction of instance key");
                ioEx.initCause(ex);
                throw ioEx;
            }
        }
	    return result;
    }

}

final class SerializableJNDIContext
    implements SerializableObjectFactory
{
    private String name;

    SerializableJNDIContext(Context ctx)
        throws IOException
    {
        try {
            // Serialize state for a jndi context.  The spec only requires
            // support for serializing contexts pointing to java:comp/env
            // or one of its subcontexts.  We also support serializing the
            // references to the the default no-arg InitialContext, as well
            // as references to the the contexts java: and java:comp. All
            // other contexts will either not serialize correctly or will
            // throw an exception during deserialization.
            this.name = ctx.getNameInNamespace();
        } catch (NamingException ex) {
            IOException ioe = new IOException();
            ioe.initCause(ex);
            throw ioe;
        }
    }

    public Object createObject(long appUniquId)
        throws IOException
    {
        try {
            if ((name == null) || (name.length() == 0)) {
                return new InitialContext();
            } else {
                return Globals.getDefaultHabitat().getService(GlassfishNamingManager.class).restoreJavaCompEnvContext(name);
            }
        } catch (NamingException namEx) {
            IOException ioe = new IOException();
            ioe.initCause(namEx);
            throw ioe;
	}
    }

}

abstract class AbstractSerializableS1ASEJBReference
    implements SerializableObjectFactory
{
    protected long containerId;
    protected String debugStr;	//used for loggin purpose only


    protected static Logger _ejbLogger =
       LogDomains.getLogger(AbstractSerializableS1ASEJBReference.class, LogDomains.EJB_LOGGER);

    AbstractSerializableS1ASEJBReference(long containerId) {
	this.containerId = containerId;
	BaseContainer container = EjbContainerUtilImpl.getInstance().getContainer(containerId);

	//container can be null if the app has been undeployed
	//  after this was serialized
	if (container == null) {
	    _ejbLogger.log(Level.WARNING, "ejb.base.io.EJBOutputStream.null_container", containerId);
	    debugStr = "" + containerId;
	} else {
	    debugStr = container.toString();
	}
    }


    protected static java.rmi.Remote doRemoteRefClassLoaderConversion
        (java.rmi.Remote reference) throws IOException {

        Thread currentThread = Thread.currentThread();
        ClassLoader contextClassLoader =
            currentThread.getContextClassLoader();

        java.rmi.Remote returnReference = reference;

        if( reference.getClass().getClassLoader() !=
            contextClassLoader) {
            try {
                byte[] serializedRef = EJBObjectOutputStreamHandler._javaEEIOUtils.serializeObject
                    (reference, false);
                returnReference = (java.rmi.Remote)
                        EJBObjectOutputStreamHandler._javaEEIOUtils.deserializeObject(serializedRef, false,
                                             contextClassLoader);
                GlassFishORBHelper orbHelper = EjbContainerUtilImpl.getInstance().getORBHelper();
                ProtocolManager protocolMgr = orbHelper.getProtocolManager();

               protocolMgr.connectObject(returnReference);

            } catch(IOException ioe) {
                throw ioe;
            } catch(Exception e) {
                IOException ioEx = new IOException(e.getMessage());
                ioEx.initCause(e);
                throw ioEx;
            }
        }

        return returnReference;
    }
}

final class SerializableS1ASEJBHomeReference
    extends AbstractSerializableS1ASEJBReference
{

    SerializableS1ASEJBHomeReference(long containerId) {
	super(containerId);
    }

    @Override
    public Object createObject(long appUniqueId)
        throws IOException
    {
	    Object result = null;
	    BaseContainer container = EjbContainerUtilImpl.getInstance().getContainer(containerId, appUniqueId);
	    //container can be null if the app has been undeployed
	    //  after this was serialized
	    if (container == null) {
	        _ejbLogger.log(Level.WARNING, "ejb.base.io.EJBOutputStream.null_container", debugStr);
	        result = null;
	    } else {
            // Note that we can assume it's a RemoteHome stub because an
            // application never sees a reference to the internal
            // Home for the Remote Business view.
	        result = AbstractSerializableS1ASEJBReference.
                doRemoteRefClassLoaderConversion(container.getEJBHomeStub());
	    }

	    return result;
    }
}

final class SerializableS1ASEJBObjectReference
    extends AbstractSerializableS1ASEJBReference
{
    private byte[] instanceKey;
    private Object sfsbKey;
    private long sfsbClientVersion;
    private boolean haEnabled;

    // If 3.0 Remote business view, the name of the remote business
    // interface to which this stub corresponds.
    private String remoteBusinessInterface;

    SerializableS1ASEJBObjectReference(long containerId, byte[] objKey,
            int keySize, String remoteBusinessInterfaceName) {
        super(containerId);
        BaseContainer container = EjbContainerUtilImpl.getInstance().getContainer(containerId);
        if (container != null) {
            this.haEnabled = container.isHAEnabled();
        }
        remoteBusinessInterface = remoteBusinessInterfaceName;
        instanceKey = new byte[keySize];
        System.arraycopy(objKey, EJBObjectOutputStreamHandler.INSTANCEKEY_OFFSET,
                instanceKey, 0, keySize);
    }

    void setSFSBClientVersion(Object key, long val) {
        this.sfsbKey = key;
        this.sfsbClientVersion = val;
    }

    boolean isHAEnabled() {
        return haEnabled;
    }

    @Override
    public Object createObject(long appUniqueId)
        throws IOException
    {
        Object result = null;
        BaseContainer container = EjbContainerUtilImpl.getInstance().getContainer(containerId, appUniqueId);
        //container can be null if the app has been undeployed
        //  after this was serialized
        if (container == null) {
            _ejbLogger.log(Level.WARNING,
                               "ejb.base.io.EJBOutputStream.null_container", debugStr);
            result = null;
        } else {
                try {
                    if( remoteBusinessInterface == null ) {
                        java.rmi.Remote reference = container.
                            createRemoteReferenceWithId(instanceKey, null);
                        result = AbstractSerializableS1ASEJBReference.
                            doRemoteRefClassLoaderConversion(reference);

                    } else {

                        String generatedRemoteIntfName = EJBUtils.
                            getGeneratedRemoteIntfName(remoteBusinessInterface);

                        java.rmi.Remote remoteRef = container.
                            createRemoteReferenceWithId(instanceKey,
                                                        generatedRemoteIntfName);

                        java.rmi.Remote newRemoteRef =
                            AbstractSerializableS1ASEJBReference.
                                doRemoteRefClassLoaderConversion(remoteRef);


                        Thread currentThread = Thread.currentThread();
                        ClassLoader contextClassLoader =
                            currentThread.getContextClassLoader();

                        result = EJBUtils.createRemoteBusinessObject
                            (contextClassLoader, remoteBusinessInterface,
                             newRemoteRef);

                    }
                    /*TODO
                    if (haEnabled) {
                        SFSBClientVersionManager.setClientVersion(
                                containerId, sfsbKey, sfsbClientVersion);
                    }*/
                } catch(Exception e) {
                    IOException ioex = new IOException("remote ref create error");
                    ioex.initCause(e);
                    throw ioex;
                }
        }

        return result;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy