dain        2005/02/10 06:00:00

  Modified:    modules/core/src/java/org/openejb/proxy
                        EJBMethodInterceptor.java EJBProxyFactory.java
                        ReplacementStrategy.java SerializationHanlder.java
  Log:

  Added support for cross classloader invocations.  The code is a bit slow but 
works.
  
  Revision  Changes    Path
  1.11      +45 -30    
openejb/modules/core/src/java/org/openejb/proxy/EJBMethodInterceptor.java
  
  Index: EJBMethodInterceptor.java
  ===================================================================
  RCS file: 
/home/projects/openejb/scm/openejb/modules/core/src/java/org/openejb/proxy/EJBMethodInterceptor.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- EJBMethodInterceptor.java 10 Feb 2005 06:38:32 -0000      1.10
  +++ EJBMethodInterceptor.java 10 Feb 2005 11:00:00 -0000      1.11
  @@ -2,7 +2,6 @@
   
   import java.io.IOException;
   import java.io.Serializable;
  -import java.io.ObjectStreamException;
   import java.lang.reflect.Method;
   import java.rmi.NoSuchObjectException;
   import java.rmi.RemoteException;
  @@ -10,8 +9,6 @@
   import javax.ejb.EJBObject;
   import javax.ejb.Handle;
   import javax.ejb.NoSuchObjectLocalException;
  -import javax.ejb.EJBHome;
  -import javax.ejb.EJBMetaData;
   
   import net.sf.cglib.proxy.MethodInterceptor;
   import net.sf.cglib.proxy.MethodProxy;
  @@ -59,6 +56,16 @@
        */
       private transient boolean shouldCopy;
   
  +    /**
  +     * The classloader of the proxy factory
  +     */
  +    private transient ClassLoader sourceClassLoader;
  +
  +    /**
  +     * Does this proxy target a container in a differenct classloader?
  +     */
  +    private transient boolean crossClassLoader;
  +
       public EJBMethodInterceptor(EJBProxyFactory proxyFactory, 
EJBInterfaceType type, EJBContainer container, int[] operationMap) {
           this(proxyFactory, type, container, operationMap, null);
       }
  @@ -71,6 +78,9 @@
           this.primaryKey = primaryKey;
   
           if (container != null) {
  +            sourceClassLoader = proxyFactory.getClassLoader();
  +            crossClassLoader = isCrossClassLoader(sourceClassLoader, 
container.getClassLoader());
  +
               // @todo REMOVE: this is a dirty dirty dirty hack to make the 
old openejb code work
               // this lets really stupid clients get access to the primary key 
of the proxy, which is readily
               // available from several other sources
  @@ -189,11 +199,19 @@
   
       private void copyArgs(Object[] args) throws IOException, 
ClassNotFoundException {
           if (args != null && args.length > 0) {
  +            ClassLoader oldCl = 
Thread.currentThread().getContextClassLoader();
               try {
  -                SerializationHanlder.setStrategy(ReplacementStrategy.COPY);
  -                SerializationHanlder.copyArgs(args);
  +                
Thread.currentThread().setContextClassLoader(sourceClassLoader);
  +                if (crossClassLoader) {
  +                    
SerializationHanlder.setStrategy(ReplacementStrategy.IN_VM_REPLACE);
  +                    SerializationHanlder.copyArgs(sourceClassLoader, args);
  +                } else {
  +                    
SerializationHanlder.setStrategy(ReplacementStrategy.COPY);
  +                    SerializationHanlder.copyArgs(args);
  +                }
               } finally {
                   SerializationHanlder.setStrategy(null);
  +                Thread.currentThread().setContextClassLoader(oldCl);
               }
           }
       }
  @@ -204,11 +222,19 @@
           }
   
           // copy the result into the current classloader
  +        ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
           try {
  -            SerializationHanlder.setStrategy(ReplacementStrategy.COPY);
  -            return SerializationHanlder.copyObj(returnObj);
  +            Thread.currentThread().setContextClassLoader(sourceClassLoader);
  +            if (crossClassLoader) {
  +                
SerializationHanlder.setStrategy(ReplacementStrategy.IN_VM_REPLACE);
  +                return SerializationHanlder.copyObj(sourceClassLoader, 
returnObj);
  +            } else {
  +                SerializationHanlder.setStrategy(ReplacementStrategy.COPY);
  +                return SerializationHanlder.copyObj(returnObj);
  +            }
           } finally {
               SerializationHanlder.setStrategy(null);
  +            Thread.currentThread().setContextClassLoader(oldCl);
           }
       }
   
  @@ -216,33 +242,22 @@
           container = proxyFactory.getContainer();
           operationMap = proxyFactory.getOperationMap(interfaceType);
   
  +        sourceClassLoader = proxyFactory.getClassLoader();
  +        crossClassLoader = isCrossClassLoader(sourceClassLoader, 
container.getClassLoader());
  +
           // @todo REMOVE: this is a dirty dirty dirty hack to make the old 
openejb code work
           // this lets really stupid clients get access to the primary key of 
the proxy, which is readily
           // available from several other sources
           this.proxyInfo = new ProxyInfo(container.getProxyInfo(), primaryKey);
       }
   
  -//    private static final class ClassLoaderCopy implements 
ReplacementStrategy {
  -//        public Object writeReplace(Object object, ProxyInfo proxyInfo) 
throws ObjectStreamException {
  -//            new EJBProxyFactory(proxyInfo);
  -//            if (object instanceof EJBObject){
  -//                return 
org.openejb.OpenEJB.getApplicationServer().getEJBObject(proxyInfo);
  -//            } else if (object instanceof EJBHome){
  -//                return 
org.openejb.OpenEJB.getApplicationServer().getEJBHome(proxyInfo);
  -//            } else if (object instanceof EJBMetaData){
  -//                return 
org.openejb.OpenEJB.getApplicationServer().getEJBMetaData(proxyInfo);
  -//            } else if (object instanceof HandleImpl){
  -//                HandleImpl handle = (HandleImpl)object;
  -//
  -//                if (handle.type == HandleImpl.HANDLE){
  -//                    return 
org.openejb.OpenEJB.getApplicationServer().getHandle(proxyInfo);
  -//                } else {
  -//                    return 
org.openejb.OpenEJB.getApplicationServer().getHomeHandle(proxyInfo);
  -//                }
  -//            } else /*should never happen */ {
  -//                return object;
  -//            }
  -//        }
  -//    };
  -//
  +    private static boolean isCrossClassLoader(ClassLoader source, 
ClassLoader target) {
  +        while (source != null) {
  +            if (source == target) {
  +                return false;
  +            }
  +            source = source.getParent();
  +        }
  +        return true;
  +    }
   }
  
  
  
  1.12      +1 -1      
openejb/modules/core/src/java/org/openejb/proxy/EJBProxyFactory.java
  
  Index: EJBProxyFactory.java
  ===================================================================
  RCS file: 
/home/projects/openejb/scm/openejb/modules/core/src/java/org/openejb/proxy/EJBProxyFactory.java,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- EJBProxyFactory.java      9 Feb 2005 02:07:55 -0000       1.11
  +++ EJBProxyFactory.java      10 Feb 2005 11:00:00 -0000      1.12
  @@ -1 +1 @@
  -/**
 * Redistribution and use of this software and associated documentation
 * ("Software"), with or without modification, are permitted provided
 * that the following conditions are met:
 *
 * 1. Redistributions of source code must retain copyright
 *    statements and notices.  Redistributions must also contain a
 *    copy of this document.
 *
 * 2. Redistributions in binary form must reproduce the
 *    above copyright notice, this list of conditions and the
 *    following disclaimer in the documentation and/or other
 *    materials provided with the distribution.
 *
 * 3. The name "OpenEJB" must not be used to endorse or promote
 *    products derived from this Software without prior written
 *    permission of The OpenEJB Group.  For written permission,
 *    please contact [EMAIL PROTECTED]
 *
 * 4. Products derived from this Software may not be called "OpenEJB"
 *    nor may "OpenEJB" appear in their names without prior written
 *    permission of The OpenEJB Group. OpenEJB is a registered
 *    trademark of The OpenEJB Group.
 *
 * 5. Due credit should be given to the OpenEJB Project
 *    (http://openejb.org/).
 *
 * THIS SOFTWARE IS PROVIDED BY THE OPENEJB GROUP AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
 * THE OPENEJB GROUP OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Copyright 2001 (C) The OpenEJB Group. All Rights Reserved.
 *
 * $Id$
 */
package org.openejb.proxy;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.ejb.EJBHome;
import javax.ejb.EJBLocalHome;
import javax.ejb.EJBLocalObject;
import javax.ejb.EJBObject;

import org.openejb.ContainerIndex;
import org.openejb.EJBContainer;
import org.openejb.EJBInterfaceType;
import org.openejb.ContainerNotFoundException;
import org.openejb.dispatch.InterfaceMethodSignature;

public class EJBProxyFactory implements Serializable, 
org.tranql.ejb.EJBProxyFactory {
    private static final Class[] sessionBaseClasses =
            new Class[]{SessionEJBObject.class, SessionEJBHome.class, 
SessionEJBLocalObject.class, SessionEJBLocalHome.class};

    private static final Class[] entityBaseClasses =
            new Class[]{EntityEJBObject.class, EntityEJBHome.class, 
EntityEJBLocalObject.class, EntityEJBLocalHome.class};

    private final String containerId;
    private final boolean isSessionBean;
    private final Class remoteInterface;
    private final Class homeInterface;
    private final Class localInterface;
    private final Class localHomeInterface;

    private transient final CglibEJBProxyFactory remoteFactory;
    private transient final CglibEJBProxyFactory homeFactory;
    private transient final CglibEJBProxyFactory localFactory;
    private transient final CglibEJBProxyFactory localHomeFactory;

    private transient EJBContainer container;

    private transient int[] remoteMap;
    private transient int[] homeMap;
    private transient int[] localMap;
    private transient int[] localHomeMap;

    private transient Map legacyMethodMap;

    public EJBProxyFactory(EJBContainer container) {
        this(container.getProxyInfo());
        setContainer(container);
    }

    public EJBProxyFactory(ProxyInfo proxyInfo) {
        this(
                proxyInfo.getContainerID(),
                proxyInfo.isSessionBean(),
                proxyInfo.getRemoteInterface(),
                proxyInfo.getHomeInterface(),
                proxyInfo.getLocalInterface(),
                proxyInfo.getLocalHomeInterface());
    }

    public EJBProxyFactory(
            String containerId,
            boolean sessionBean,
            Class remoteInterface,
            Class homeInterface,
            Class localInterface,
            Class localHomeInterface) {
        this.containerId = containerId;
        isSessionBean = sessionBean;

// JNB: these are temporarily disabled due to classloader issues during 
deployment
//        assert remoteInterface == null || (remoteInterface.isInterface() && 
EJBObject.class.isAssignableFrom(remoteInterface));
        this.remoteInterface = remoteInterface;

//        assert homeInterface == null || (homeInterface.isInterface() && 
EJBHome.class.isAssignableFrom(homeInterface));
        this.homeInterface = homeInterface;

//        assert localInterface == null || (localInterface.isInterface() && 
EJBLocalObject.class.isAssignableFrom(localInterface));
        this.localInterface = localInterface;

//        assert localHomeInterface == null || 
(localHomeInterface.isInterface() && 
EJBLocalHome.class.isAssignableFrom(localHomeInterface));
        this.localHomeInterface = localHomeInterface;

        this.remoteFactory = getFactory(EJBInterfaceType.REMOTE.getOrdinal(), 
remoteInterface);
        this.homeFactory = getFactory(EJBInterfaceType.HOME.getOrdinal(), 
homeInterface);
        this.localFactory = getFactory(EJBInterfaceType.LOCAL.getOrdinal(), 
localInterface);
        this.localHomeFactory = 
getFactory(EJBInterfaceType.LOCALHOME.getOrdinal(), localHomeInterface);
    }

    public String getEJBName() {
        return container.getEJBName();
    }

    EJBContainer getContainer() throws ContainerNotFoundException {
        if (container == null) {
            locateContainer();
        }
        return container;
    }

    private void setContainer(EJBContainer container) {
        assert container != null: "container is null";
        this.container = container;

        ProxyInfo proxyInfo = container.getProxyInfo();
        InterfaceMethodSignature[] signatures = container.getSignatures();

        // build the legacy map
        Map map = new HashMap();
        addLegacyMethods(map, proxyInfo.getRemoteInterface(), signatures);
        addLegacyMethods(map, proxyInfo.getHomeInterface(), signatures);
        addLegacyMethods(map, proxyInfo.getLocalInterface(), signatures);
        addLegacyMethods(map, proxyInfo.getLocalHomeInterface(), signatures);
        legacyMethodMap = Collections.unmodifiableMap(map);

        remoteMap = createOperationsMap(remoteFactory, signatures);
        homeMap = createOperationsMap(homeFactory, signatures);

        localMap = createOperationsMap(localFactory, signatures);
        localHomeMap = createOperationsMap(localHomeFactory, signatures);
    }

    int[] getOperationMap(EJBInterfaceType type) throws 
ContainerNotFoundException {
        if (container == null) {
            locateContainer();
        }

        if (type == EJBInterfaceType.REMOTE) {
            return remoteMap;
        } else if (type == EJBInterfaceType.HOME) {
            return homeMap;
        } else if (type == EJBInterfaceType.LOCAL) {
            return localMap;
        } else if (type == EJBInterfaceType.LOCALHOME) {
            return localHomeMap;
        } else {
            throw new IllegalArgumentException("Unsupported interface type " + 
type);
        }
    }

    public int getMethodIndex(Method method) {
        Integer index = (Integer) legacyMethodMap.get(method);
        if (index == null) {
            index = new Integer(-1);
        }
        return index.intValue();
    }

    public Class getLocalInterfaceClass() {
        return localInterface;
    }

    public Class getRemoteInterfaceClass() {
        return remoteInterface;
    }

    /**
     * Return a proxy for the EJB's remote interface. This can be passed back
     * to any client that wishes to access the EJB (e.g. in response to a
     * call to SessionContext.getEJBObject() )
     * @return the proxy for this EJB's home interface
     */
    public EJBObject getEJBObject(Object primaryKey) {
        EJBMethodInterceptor handler = new EJBMethodInterceptor(
                this,
                EJBInterfaceType.REMOTE,
                container,
                remoteMap,
                primaryKey);
        return (EJBObject) remoteFactory.create(handler);
    }

    /**
     * Return a proxy for the EJB's home interface. This can be passed back
     * to any client that wishes to access the EJB (e.g. in response to a
     * call to EJBContext.getEJBHome() )
     * @return the proxy for this EJB's home interface
     */
    public EJBHome getEJBHome() {
        EJBMethodInterceptor handler = new EJBMethodInterceptor(
                this,
                EJBInterfaceType.HOME,
                container,
                homeMap);
        return (EJBHome) homeFactory.create(handler);
    }

    /**
     * Return a proxy for the EJB's local interface. This can be passed back
     * to any client that wishes to access the EJB (e.g. in response to a
     * call to SessionContext.getEJBLocalObject() )
     * @return the proxy for this EJB's local interface
     */

    public EJBLocalObject getEJBLocalObject(Object primaryKey) {
        EJBMethodInterceptor handler = new EJBMethodInterceptor(
                this,
                EJBInterfaceType.LOCAL,
                container,
                localMap,
                primaryKey);
        return (EJBLocalObject) localFactory.create(handler);
    }

    /**
     * Return a proxy for the EJB's local home interface. This can be
     * passed back to any client that wishes to access the EJB
     * (e.g. in response to a call to EJBContext.getEJBLocalHome() )
     * @return the proxy for this EJB's local home interface
     */

    public EJBLocalHome getEJBLocalHome() {
        EJBMethodInterceptor handler = new EJBMethodInterceptor(
                this,
                EJBInterfaceType.LOCALHOME,
                container,
                localHomeMap);
        return (EJBLocalHome) localHomeFactory.create(handler);
    }

    private int[] createOperationsMap(CglibEJBProxyFactory factory, 
InterfaceMethodSignature[] signatures) {
        if (factory == null) return new int[0];
        return EJBProxyHelper.getOperationMap(factory.getType(), signatures, 
false);
    }

    private CglibEJBProxyFactory getFactory(int interfaceType, Class 
interfaceClass) {
        if (interfaceClass == null) {
            return null;
        }

        Class baseClass;
        if (isSessionBean) {
            baseClass = sessionBaseClasses[interfaceType];
        } else {
            baseClass = entityBaseClasses[interfaceType];
        }
        return new CglibEJBProxyFactory(baseClass, interfaceClass);
    }

    private static void addLegacyMethods(Map legacyMethodMap, Class clazz, 
InterfaceMethodSignature[] signatures) {
        if (clazz == null) {
            return;
        }

        for (int i = 0; i < signatures.length; i++) {
            InterfaceMethodSignature signature = signatures[i];
            Method method = signature.getMethod(clazz);
            if (method != null) {
                legacyMethodMap.put(method, new Integer(i));
            }
        }
    }

    private void locateContainer() throws ContainerNotFoundException {
        ContainerIndex containerIndex = ContainerIndex.getInstance();
        EJBContainer c = containerIndex.getContainer(containerId);
        if (c == null) {
            throw new IllegalStateException("Contianer not found: " + 
containerId);
        }
        setContainer(c);
    }

    private Object readResolve() {
        return new EJBProxyFactory(
                containerId,
                isSessionBean,
                remoteInterface,
                homeInterface,
                localInterface,
                localHomeInterface);
    }
}

  \ No newline at end of file
  +/**
 * Redistribution and use of this software and associated documentation
 * ("Software"), with or without modification, are permitted provided
 * that the following conditions are met:
 *
 * 1. Redistributions of source code must retain copyright
 *    statements and notices.  Redistributions must also contain a
 *    copy of this document.
 *
 * 2. Redistributions in binary form must reproduce the
 *    above copyright notice, this list of conditions and the
 *    following disclaimer in the documentation and/or other
 *    materials provided with the distribution.
 *
 * 3. The name "OpenEJB" must not be used to endorse or promote
 *    products derived from this Software without prior written
 *    permission of The OpenEJB Group.  For written permission,
 *    please contact [EMAIL PROTECTED]
 *
 * 4. Products derived from this Software may not be called "OpenEJB"
 *    nor may "OpenEJB" appear in their names without prior written
 *    permission of The OpenEJB Group. OpenEJB is a registered
 *    trademark of The OpenEJB Group.
 *
 * 5. Due credit should be given to the OpenEJB Project
 *    (http://openejb.org/).
 *
 * THIS SOFTWARE IS PROVIDED BY THE OPENEJB GROUP AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
 * THE OPENEJB GROUP OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Copyright 2001 (C) The OpenEJB Group. All Rights Reserved.
 *
 * $Id$
 */
package org.openejb.proxy;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.ejb.EJBHome;
import javax.ejb.EJBLocalHome;
import javax.ejb.EJBLocalObject;
import javax.ejb.EJBObject;

import org.openejb.ContainerIndex;
import org.openejb.EJBContainer;
import org.openejb.EJBInterfaceType;
import org.openejb.ContainerNotFoundException;
import org.openejb.dispatch.InterfaceMethodSignature;

public class EJBProxyFactory implements Serializable, 
org.tranql.ejb.EJBProxyFactory {
    private static final Class[] sessionBaseClasses =
            new Class[]{SessionEJBObject.class, SessionEJBHome.class, 
SessionEJBLocalObject.class, SessionEJBLocalHome.class};

    private static final Class[] entityBaseClasses =
            new Class[]{EntityEJBObject.class, EntityEJBHome.class, 
EntityEJBLocalObject.class, EntityEJBLocalHome.class};

    private final String containerId;
    private final boolean isSessionBean;
    private final Class remoteInterface;
    private final Class homeInterface;
    private final Class localInterface;
    private final Class localHomeInterface;

    private transient final CglibEJBProxyFactory remoteFactory;
    private transient final CglibEJBProxyFactory homeFactory;
    private transient final CglibEJBProxyFactory localFactory;
    private transient final CglibEJBProxyFactory localHomeFactory;

    private transient EJBContainer container;

    private transient int[] remoteMap;
    private transient int[] homeMap;
    private transient int[] localMap;
    private transient int[] localHomeMap;

    private transient Map legacyMethodMap;

    public EJBProxyFactory(EJBContainer container) {
        this(container.getProxyInfo());
        setContainer(container);
    }

    public EJBProxyFactory(ProxyInfo proxyInfo) {
        this(
                proxyInfo.getContainerID(),
                proxyInfo.isSessionBean(),
                proxyInfo.getRemoteInterface(),
                proxyInfo.getHomeInterface(),
                proxyInfo.getLocalInterface(),
                proxyInfo.getLocalHomeInterface());
    }

    public EJBProxyFactory(
            String containerId,
            boolean sessionBean,
            Class remoteInterface,
            Class homeInterface,
            Class localInterface,
            Class localHomeInterface) {
        this.containerId = containerId;
        isSessionBean = sessionBean;

// JNB: these are temporarily disabled due to classloader issues during 
deployment
//        assert remoteInterface == null || (remoteInterface.isInterface() && 
EJBObject.class.isAssignableFrom(remoteInterface));
        this.remoteInterface = remoteInterface;

//        assert homeInterface == null || (homeInterface.isInterface() && 
EJBHome.class.isAssignableFrom(homeInterface));
        this.homeInterface = homeInterface;

//        assert localInterface == null || (localInterface.isInterface() && 
EJBLocalObject.class.isAssignableFrom(localInterface));
        this.localInterface = localInterface;

//        assert localHomeInterface == null || 
(localHomeInterface.isInterface() && 
EJBLocalHome.class.isAssignableFrom(localHomeInterface));
        this.localHomeInterface = localHomeInterface;

        this.remoteFactory = getFactory(EJBInterfaceType.REMOTE.getOrdinal(), 
remoteInterface);
        this.homeFactory = getFactory(EJBInterfaceType.HOME.getOrdinal(), 
homeInterface);
        this.localFactory = getFactory(EJBInterfaceType.LOCAL.getOrdinal(), 
localInterface);
        this.localHomeFactory = 
getFactory(EJBInterfaceType.LOCALHOME.getOrdinal(), localHomeInterface);
    }

    public String getEJBName() {
        return container.getEJBName();
    }

    EJBContainer getContainer() throws ContainerNotFoundException {
        if (container == null) {
            locateContainer();
        }
        return container;
    }

    private void setContainer(EJBContainer container) {
        assert container != null: "container is null";
        this.container = container;

        ProxyInfo proxyInfo = container.getProxyInfo();
        InterfaceMethodSignature[] signatures = container.getSignatures();

        // build the legacy map
        Map map = new HashMap();
        addLegacyMethods(map, proxyInfo.getRemoteInterface(), signatures);
        addLegacyMethods(map, proxyInfo.getHomeInterface(), signatures);
        addLegacyMethods(map, proxyInfo.getLocalInterface(), signatures);
        addLegacyMethods(map, proxyInfo.getLocalHomeInterface(), signatures);
        legacyMethodMap = Collections.unmodifiableMap(map);

        remoteMap = createOperationsMap(remoteFactory, signatures);
        homeMap = createOperationsMap(homeFactory, signatures);

        localMap = createOperationsMap(localFactory, signatures);
        localHomeMap = createOperationsMap(localHomeFactory, signatures);
    }

    public ClassLoader getClassLoader() {
        if (remoteFactory != null) {
            return remoteFactory.getType().getClassLoader();
        } else {
            return localFactory.getType().getClassLoader();
        }
    }

    int[] getOperationMap(EJBInterfaceType type) throws 
ContainerNotFoundException {
        if (container == null) {
            locateContainer();
        }

        if (type == EJBInterfaceType.REMOTE) {
            return remoteMap;
        } else if (type == EJBInterfaceType.HOME) {
            return homeMap;
        } else if (type == EJBInterfaceType.LOCAL) {
            return localMap;
        } else if (type == EJBInterfaceType.LOCALHOME) {
            return localHomeMap;
        } else {
            throw new IllegalArgumentException("Unsupported interface type " + 
type);
        }
    }

    public int getMethodIndex(Method method) {
        Integer index = (Integer) legacyMethodMap.get(method);
        if (index == null) {
            index = new Integer(-1);
        }
        return index.intValue();
    }

    public Class getLocalInterfaceClass() {
        return localInterface;
    }

    public Class getRemoteInterfaceClass() {
        return remoteInterface;
    }

    /**
     * Return a proxy for the EJB's remote interface. This can be passed back
     * to any client that wishes to access the EJB (e.g. in response to a
     * call to SessionContext.getEJBObject() )
     * @return the proxy for this EJB's home interface
     */
    public EJBObject getEJBObject(Object primaryKey) {
        EJBMethodInterceptor handler = new EJBMethodInterceptor(
                this,
                EJBInterfaceType.REMOTE,
                container,
                remoteMap,
                primaryKey);
        return (EJBObject) remoteFactory.create(handler);
    }

    /**
     * Return a proxy for the EJB's home interface. This can be passed back
     * to any client that wishes to access the EJB (e.g. in response to a
     * call to EJBContext.getEJBHome() )
     * @return the proxy for this EJB's home interface
     */
    public EJBHome getEJBHome() {
        EJBMethodInterceptor handler = new EJBMethodInterceptor(
                this,
                EJBInterfaceType.HOME,
                container,
                homeMap);
        return (EJBHome) homeFactory.create(handler);
    }

    /**
     * Return a proxy for the EJB's local interface. This can be passed back
     * to any client that wishes to access the EJB (e.g. in response to a
     * call to SessionContext.getEJBLocalObject() )
     * @return the proxy for this EJB's local interface
     */

    public EJBLocalObject getEJBLocalObject(Object primaryKey) {
        EJBMethodInterceptor handler = new EJBMethodInterceptor(
                this,
                EJBInterfaceType.LOCAL,
                container,
                localMap,
                primaryKey);
        return (EJBLocalObject) localFactory.create(handler);
    }

    /**
     * Return a proxy for the EJB's local home interface. This can be
     * passed back to any client that wishes to access the EJB
     * (e.g. in response to a call to EJBContext.getEJBLocalHome() )
     * @return the proxy for this EJB's local home interface
     */

    public EJBLocalHome getEJBLocalHome() {
        EJBMethodInterceptor handler = new EJBMethodInterceptor(
                this,
                EJBInterfaceType.LOCALHOME,
                container,
                localHomeMap);
        return (EJBLocalHome) localHomeFactory.create(handler);
    }

    private int[] createOperationsMap(CglibEJBProxyFactory factory, 
InterfaceMethodSignature[] signatures) {
        if (factory == null) return new int[0];
        return EJBProxyHelper.getOperationMap(factory.getType(), signatures, 
false);
    }

    private CglibEJBProxyFactory getFactory(int interfaceType, Class 
interfaceClass) {
        if (interfaceClass == null) {
            return null;
        }

        Class baseClass;
        if (isSessionBean) {
            baseClass = sessionBaseClasses[interfaceType];
        } else {
            baseClass = entityBaseClasses[interfaceType];
        }
        return new CglibEJBProxyFactory(baseClass, interfaceClass);
    }

    private static void addLegacyMethods(Map legacyMethodMap, Class clazz, 
InterfaceMethodSignature[] signatures) {
        if (clazz == null) {
            return;
        }

        for (int i = 0; i < signatures.length; i++) {
            InterfaceMethodSignature signature = signatures[i];
            Method method = signature.getMethod(clazz);
            if (method != null) {
                legacyMethodMap.put(method, new Integer(i));
            }
        }
    }

    private void locateContainer() throws ContainerNotFoundException {
        ContainerIndex containerIndex = ContainerIndex.getInstance();
        EJBContainer c = containerIndex.getContainer(containerId);
        if (c == null) {
            throw new IllegalStateException("Contianer not found: " + 
containerId);
        }
        setContainer(c);
    }

    private Object readResolve() {
        return new EJBProxyFactory(
                containerId,
                isSessionBean,
                remoteInterface,
                homeInterface,
                localInterface,
                localHomeInterface);
    }
}

  \ No newline at end of file
  
  
  
  1.4       +108 -6    
openejb/modules/core/src/java/org/openejb/proxy/ReplacementStrategy.java
  
  Index: ReplacementStrategy.java
  ===================================================================
  RCS file: 
/home/projects/openejb/scm/openejb/modules/core/src/java/org/openejb/proxy/ReplacementStrategy.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- ReplacementStrategy.java  21 Mar 2004 21:26:35 -0000      1.3
  +++ ReplacementStrategy.java  10 Feb 2005 11:00:00 -0000      1.4
  @@ -45,30 +45,36 @@
   package org.openejb.proxy;

   

   import java.io.ObjectStreamException;

  +import java.io.Serializable;

  +import java.io.InvalidClassException;

  +import java.io.InvalidObjectException;

  +import java.rmi.RemoteException;

   

   import javax.ejb.EJBHome;

   import javax.ejb.EJBMetaData;

   import javax.ejb.EJBObject;

   

  +import org.openejb.EJBComponentType;

  +import org.apache.geronimo.kernel.ClassLoading;

   

  -public interface ReplacementStrategy {

   

  +public interface ReplacementStrategy {

       Object writeReplace(Object object, ProxyInfo proxyInfo) throws 
ObjectStreamException ;

       

       static final ReplacementStrategy COPY = new ReplacementStrategy(){

  -        public Object writeReplace(Object object, ProxyInfo proxyInfo) 
throws ObjectStreamException {

  +        public Object writeReplace(Object object, ProxyInfo proxyInfo) {

               return new ImmutableArtifact(object);

           }

       };

       

       static final ReplacementStrategy PASSIVATE = new ReplacementStrategy(){

  -        public Object writeReplace(Object object, ProxyInfo proxyInfo) 
throws ObjectStreamException {

  +        public Object writeReplace(Object object, ProxyInfo proxyInfo) {

               return object;

           }

       };

       

       static final ReplacementStrategy REPLACE = new ReplacementStrategy(){

  -        public Object writeReplace(Object object, ProxyInfo proxyInfo) 
throws ObjectStreamException {

  +        public Object writeReplace(Object object, ProxyInfo proxyInfo) {

               //TODO: I have plans to clean/speed this up.  This really only 
happens on serialization to an external VM, so it isn't much of a performance 
issue anyway.

               

               if (object instanceof EJBObject){

  @@ -90,6 +96,102 @@
               }

           }

       };

  -    

   

  +

  +    static final ReplacementStrategy IN_VM_REPLACE = new 
ReplacementStrategy(){

  +        public Object writeReplace(Object object, ProxyInfo proxyInfo) {

  +            if (object instanceof EJBObject){

  +                return new ProxyMemento(proxyInfo, ProxyMemento.EJB_OBJECT);

  +            } else if (object instanceof EJBHome){

  +                return new ProxyMemento(proxyInfo, ProxyMemento.EJB_HOME);

  +            } else if (object instanceof EJBMetaData){

  +                return new ProxyMemento(proxyInfo, 
ProxyMemento.EJB_META_DATA);

  +            } else if (object instanceof HandleImpl){

  +                HandleImpl handle = (HandleImpl)object;

  +

  +                if (handle.type == HandleImpl.HANDLE){

  +                    return new ProxyMemento(proxyInfo, ProxyMemento.HANDLE);

  +                } else {

  +                    return new ProxyMemento(proxyInfo, 
ProxyMemento.HOME_HANDLE);

  +                }

  +            } else /*should never happen */ {

  +                return object;

  +            }

  +        }

  +    };

  +

  +    static class ProxyMemento implements Serializable {

  +        private static final int EJB_OBJECT = 0;

  +        private static final int EJB_HOME = 1;

  +        private static final int HANDLE = 2;

  +        private static final int HOME_HANDLE = 3;

  +        private static final int EJB_META_DATA = 4;

  +

  +        private final String containerId;

  +        private final boolean isSessionBean;

  +        private final String remoteInterfaceName;

  +        private final String homeInterfaceName;

  +        private final Object primayKey;

  +        private final int type;

  +

  +        public ProxyMemento(ProxyInfo proxyInfo, int type) {

  +            this.type = type;

  +            this.containerId = proxyInfo.getContainerID();

  +            int componentType = proxyInfo.getComponentType();

  +            isSessionBean = (componentType == EJBComponentType.STATELESS || 
componentType == EJBComponentType.STATEFUL);

  +            this.remoteInterfaceName = 
proxyInfo.getRemoteInterface().getName();

  +            this.homeInterfaceName = proxyInfo.getHomeInterface().getName();

  +            this.primayKey = proxyInfo.getPrimaryKey();

  +        }

  +

  +        private Object readResolve() throws ObjectStreamException {

  +            ClassLoader cl = Thread.currentThread().getContextClassLoader();

  +            Class remoteInterface = null;

  +            try {

  +                remoteInterface = 
ClassLoading.loadClass(remoteInterfaceName, cl);

  +            } catch (ClassNotFoundException e) {

  +                throw new InvalidClassException("Could not load remote 
interface: " + remoteInterfaceName);

  +            }

  +            Class homeInterface = null;

  +            try {

  +                homeInterface = ClassLoading.loadClass(homeInterfaceName, 
cl);

  +            } catch (ClassNotFoundException e) {

  +                throw new InvalidClassException("Could not load home 
interface: " + remoteInterfaceName);

  +            }

  +

  +            EJBProxyFactory proxyFactory = new EJBProxyFactory(containerId,

  +                    isSessionBean,

  +                    remoteInterface,

  +                    homeInterface,

  +                    null,

  +                    null);

  +

  +            switch (type) {

  +                case EJB_OBJECT:

  +                    return proxyFactory.getEJBObject(primayKey);

  +                case EJB_HOME:

  +                    return proxyFactory.getEJBHome();

  +                case HANDLE:

  +                    try {

  +                        return 
proxyFactory.getEJBObject(primayKey).getHandle();

  +                    } catch (RemoteException e) {

  +                        throw (InvalidObjectException) new 
InvalidObjectException("Error getting handle from ejb object").initCause(e);

  +                    }

  +                case HOME_HANDLE:

  +                    try {

  +                        return proxyFactory.getEJBHome().getHomeHandle();

  +                    } catch (RemoteException e) {

  +                        throw (InvalidObjectException) new 
InvalidObjectException("Error getting handle from home").initCause(e);

  +                    }

  +                case EJB_META_DATA:

  +                    try {

  +                        return proxyFactory.getEJBHome().getEJBMetaData();

  +                    } catch (RemoteException e) {

  +                        throw (InvalidObjectException) new 
InvalidObjectException("Error getting ejb meta data from home").initCause(e);

  +                    }

  +                default:

  +                    throw new InvalidObjectException("Unknown type" + type);

  +            }

  +        }

  +    }

   }

  
  
  
  1.5       +23 -1     
openejb/modules/core/src/java/org/openejb/proxy/SerializationHanlder.java
  
  Index: SerializationHanlder.java
  ===================================================================
  RCS file: 
/home/projects/openejb/scm/openejb/modules/core/src/java/org/openejb/proxy/SerializationHanlder.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- SerializationHanlder.java 10 Feb 2005 06:38:32 -0000      1.4
  +++ SerializationHanlder.java 10 Feb 2005 11:00:00 -0000      1.5
  @@ -46,8 +46,13 @@
   

   import java.io.IOException;

   import java.io.ObjectStreamException;

  +import java.io.ByteArrayOutputStream;

  +import java.io.ObjectOutputStream;

  +import java.io.ByteArrayInputStream;

   import java.rmi.MarshalledObject;

   

  +import org.apache.geronimo.kernel.ObjectInputStreamExt;

  +

   

   public class SerializationHanlder {

       private static InheritableThreadLocal serializationState = new 
InheritableThreadLocal();

  @@ -82,6 +87,23 @@
   

       public static Object writeReplace(Object object, ProxyInfo proxyInfo) 
throws ObjectStreamException {

           return getStrategy().writeReplace(object, proxyInfo);

  +    }

  +

  +    public static void copyArgs(ClassLoader classLoader, Object[] objects) 
throws IOException, ClassNotFoundException {

  +        for (int i = 0; i < objects.length; i++) {

  +            objects[i] = copyObj(classLoader, objects[i]);

  +        }

  +    }

  +

  +    public static Object copyObj(ClassLoader classLoader, Object object) 
throws IOException, ClassNotFoundException {

  +        ByteArrayOutputStream baos = new ByteArrayOutputStream();

  +        ObjectOutputStream oos = new ObjectOutputStream(baos);

  +        oos.writeObject(object);

  +        oos.flush();

  +        oos.close();

  +        ByteArrayInputStream bais = new 
ByteArrayInputStream(baos.toByteArray());

  +        ObjectInputStreamExt ois = new ObjectInputStreamExt(bais, 
classLoader);

  +        return ois.readObject();

       }

   }

   

  
  
  

Reply via email to