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();
}
}