| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.openejb.core.ivm; |
| |
| import org.apache.openejb.BeanContext; |
| import org.apache.openejb.BeanType; |
| import org.apache.openejb.InterfaceType; |
| import org.apache.openejb.OpenEJBException; |
| import org.apache.openejb.OpenEJBRuntimeException; |
| import org.apache.openejb.ProxyInfo; |
| import org.apache.openejb.RpcContainer; |
| import org.apache.openejb.core.ThreadContext; |
| import org.apache.openejb.loader.SystemInstance; |
| import org.apache.openejb.spi.ContainerSystem; |
| import org.apache.openejb.spi.SecurityService; |
| import org.apache.openejb.util.proxy.LocalBeanProxyFactory; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.io.IOException; |
| import java.io.NotSerializableException; |
| import java.io.ObjectInputStream; |
| import java.io.ObjectOutputStream; |
| import java.io.ObjectStreamException; |
| import java.io.Serializable; |
| import java.lang.ref.WeakReference; |
| import java.lang.reflect.InvocationHandler; |
| import java.lang.reflect.Method; |
| import java.lang.reflect.Proxy; |
| import java.math.BigDecimal; |
| import java.rmi.AccessException; |
| import java.rmi.NoSuchObjectException; |
| import java.rmi.Remote; |
| import java.rmi.RemoteException; |
| import java.util.ArrayList; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Set; |
| import java.util.WeakHashMap; |
| import java.util.concurrent.ConcurrentHashMap; |
| import java.util.concurrent.ConcurrentMap; |
| import java.util.concurrent.locks.ReentrantLock; |
| import javax.ejb.AccessLocalException; |
| import javax.ejb.EJBException; |
| import javax.ejb.EJBTransactionRequiredException; |
| import javax.ejb.EJBTransactionRolledbackException; |
| import javax.ejb.NoSuchEJBException; |
| import javax.ejb.NoSuchObjectLocalException; |
| import javax.ejb.TransactionRequiredLocalException; |
| import javax.ejb.TransactionRolledbackLocalException; |
| import javax.transaction.TransactionRequiredException; |
| import javax.transaction.TransactionRolledbackException; |
| |
| import static org.apache.openejb.core.ivm.IntraVmCopyMonitor.State.CLASSLOADER_COPY; |
| import static org.apache.openejb.core.ivm.IntraVmCopyMonitor.State.COPY; |
| import static org.apache.openejb.core.ivm.IntraVmCopyMonitor.State.NONE; |
| |
| @SuppressWarnings("unchecked") |
| public abstract class BaseEjbProxyHandler implements InvocationHandler, Serializable { |
| |
| private static final String OPENEJB_LOCALCOPY = "openejb.localcopy"; |
| private static final boolean REMOTE_COPY_ENABLED = parseRemoteCopySetting(); |
| public final Object deploymentID; |
| public final Object primaryKey; |
| protected final InterfaceType interfaceType; |
| private final ReentrantLock lock = new ReentrantLock(); |
| public boolean inProxyMap; |
| public transient RpcContainer container; |
| protected boolean isInvalidReference; |
| protected Object clientIdentity; |
| private IntraVmCopyMonitor.State strategy = NONE; |
| private transient WeakReference<BeanContext> beanContextRef; |
| /* |
| * The EJB 1.1 specification requires that arguments and return values between beans adhere to the |
| * Java RMI copy semantics which requires that the all arguments be passed by value (copied) and |
| * never passed as references. However, it is possible for the system administrator to turn off the |
| * copy operation so that arguments and return values are passed by reference as performance optimization. |
| * Simply setting the org.apache.openejb.core.EnvProps.INTRA_VM_COPY property to FALSE will cause this variable to |
| * set to false, and therefor bypass the copy operations in the invoke( ) method of this class; arguments |
| * and return values will be passed by reference not value. |
| * |
| * This property is, by default, always TRUE but it can be changed to FALSE by setting it as a System property |
| * or a property of the Property argument when invoking OpenEJB.init(props). This variable is set to that |
| * property in the static block for this class. |
| */ |
| private boolean doIntraVmCopy; |
| private boolean doCrossClassLoaderCopy; |
| private transient WeakHashMap<Class, Object> interfaces; |
| private transient WeakReference<Class> mainInterface; |
| |
| public BaseEjbProxyHandler(final BeanContext beanContext, final Object pk, final InterfaceType interfaceType, List<Class> interfaces, Class mainInterface) { |
| this.container = (RpcContainer) beanContext.getContainer(); |
| this.deploymentID = beanContext.getDeploymentID(); |
| this.interfaceType = interfaceType; |
| this.primaryKey = pk; |
| this.setBeanContext(beanContext); |
| |
| if (interfaces == null || interfaces.size() == 0) { |
| final InterfaceType objectInterfaceType = interfaceType.isHome() ? interfaceType.getCounterpart() : interfaceType; |
| interfaces = new ArrayList<Class>(beanContext.getInterfaces(objectInterfaceType)); |
| } |
| |
| if (mainInterface == null && interfaces.size() == 1) { |
| mainInterface = interfaces.get(0); |
| } |
| |
| setInterfaces(interfaces); |
| setMainInterface(mainInterface); |
| if (mainInterface == null) { |
| throw new IllegalArgumentException("No mainInterface: otherwise di: " + beanContext + " InterfaceType: " + interfaceType + " interfaces: " + interfaces); |
| } |
| this.setDoIntraVmCopy(REMOTE_COPY_ENABLED && !interfaceType.isLocal() && !interfaceType.isLocalBean()); |
| } |
| |
| private static boolean parseRemoteCopySetting() { |
| return SystemInstance.get().getOptions().get(OPENEJB_LOCALCOPY, true); |
| } |
| |
| protected void setDoIntraVmCopy(final boolean doIntraVmCopy) { |
| this.doIntraVmCopy = doIntraVmCopy; |
| setStrategy(); |
| } |
| |
| protected void setDoCrossClassLoaderCopy(final boolean doCrossClassLoaderCopy) { |
| this.doCrossClassLoaderCopy = doCrossClassLoaderCopy; |
| setStrategy(); |
| } |
| |
| private void setStrategy() { |
| if (!doIntraVmCopy) { |
| strategy = NONE; |
| } else if (doCrossClassLoaderCopy) { |
| strategy = CLASSLOADER_COPY; |
| } else { |
| strategy = COPY; |
| } |
| } |
| |
| /** |
| * This method should be called to determine the corresponding |
| * business interface class to name as the invoking interface. |
| * This method should NOT be called on non-business-interface |
| * methods the proxy has such as java.lang.Object or IntraVmProxy. |
| * |
| * @param method Method |
| * @return the business (or component) interface matching this method |
| */ |
| protected Class<?> getInvokedInterface(final Method method) { |
| // Home's only have one interface ever. We don't |
| // need to verify that the method invoked is in |
| // it's interface. |
| final Class mainInterface = getMainInterface(); |
| if (interfaceType.isHome()) { |
| return mainInterface; |
| } |
| if (interfaceType.isLocalBean()) { |
| return mainInterface; |
| } |
| |
| final Class declaringClass = method.getDeclaringClass(); |
| |
| // If our "main" interface is or extends the method's declaring class |
| // then we're good. We know the main interface has the method being |
| // invoked and it's safe to return it as the invoked interface. |
| if (mainInterface != null && declaringClass.isAssignableFrom(mainInterface)) { |
| return mainInterface; |
| } |
| |
| // If the method being invoked isn't in the "main" interface |
| // we need to find a suitable interface or throw an exception. |
| for (final Class secondaryInterface : interfaces.keySet()) { |
| if (declaringClass.isAssignableFrom(secondaryInterface)) { |
| return secondaryInterface; |
| } |
| } |
| |
| // We couldn't find an implementing interface. Where did this |
| // method come from??? Freak occurence. Throw an exception. |
| throw new IllegalStateException("Received method invocation and cannot determine corresponding business interface: method=" + method); |
| } |
| |
| public Class getMainInterface() { |
| return mainInterface.get(); |
| } |
| |
| private void setMainInterface(final Class referent) { |
| mainInterface = new WeakReference<Class>(referent); |
| } |
| |
| public List<Class> getInterfaces() { |
| final Set<Class> classes = interfaces.keySet(); |
| final List<Class> list = new ArrayList<Class>(); |
| final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); |
| for (final Class<?> clazz : classes) { // convert interfaces with current classloader -> relevant for remote interfaces |
| if (clazz.isInterface() && getBeanContext().getInterfaceType(clazz) == InterfaceType.BUSINESS_REMOTE) { |
| try { |
| list.add(contextClassLoader.loadClass(clazz.getName())); |
| } catch (final ClassNotFoundException e) { |
| list.add(clazz); |
| } catch (final NoClassDefFoundError e) { |
| list.add(clazz); |
| } |
| } else { |
| list.add(clazz); |
| } |
| } |
| return list; |
| } |
| |
| private void setInterfaces(final List<Class> interfaces) { |
| this.interfaces = new WeakHashMap<Class, Object>(interfaces.size()); |
| for (final Class clazz : interfaces) { |
| this.interfaces.put(clazz, null); |
| } |
| } |
| |
| protected void checkAuthorization(final Method method) throws OpenEJBException { |
| } |
| |
| public void setIntraVmCopyMode(final boolean on) { |
| setDoIntraVmCopy(on); |
| } |
| |
| @Override |
| public Object invoke(final Object proxy, Method method, Object[] args) throws Throwable { |
| try { |
| isValidReference(method); |
| } catch (final IllegalStateException ise) { |
| // bean was undeployed |
| if (method.getName().equals("writeReplace")) { // session serialization, we just need to replace this |
| final BeanContext beanContext = beanContextRef.get(); |
| if (beanContext != null) { |
| return _writeReplace(proxy); |
| } |
| } |
| throw ise; |
| } |
| |
| if (args == null) { |
| args = new Object[]{}; |
| } |
| |
| if (method.getDeclaringClass() == Object.class) { |
| final String methodName = method.getName(); |
| |
| if (methodName.equals("toString")) { |
| return toString(); |
| } else if (methodName.equals("equals")) { |
| return equals(args[0]) ? Boolean.TRUE : Boolean.FALSE; |
| } else if (methodName.equals("hashCode")) { |
| return hashCode(); |
| } else { |
| throw new UnsupportedOperationException("Unknown method: " + method); |
| } |
| } else if (method.getDeclaringClass() == IntraVmProxy.class) { |
| final String methodName = method.getName(); |
| |
| if (methodName.equals("writeReplace")) { |
| return _writeReplace(proxy); |
| } else { |
| throw new UnsupportedOperationException("Unknown method: " + method); |
| } |
| } else if (method.getDeclaringClass() == BeanContext.Removable.class) { |
| return _invoke(proxy, BeanContext.Removable.class, method, args); |
| } |
| |
| Class interfce = getInvokedInterface(method); |
| |
| final ThreadContext callContext = ThreadContext.getThreadContext(); |
| final Object localClientIdentity = ClientSecurity.getIdentity(); |
| try { |
| if (callContext == null && localClientIdentity != null) { |
| final SecurityService securityService = SystemInstance.get().getComponent(SecurityService.class); |
| if(null == securityService){ |
| throw new OpenEJBRuntimeException("SecurityService has not been initialized"); |
| } |
| securityService.associate(localClientIdentity); |
| } |
| if (strategy == CLASSLOADER_COPY || getBeanContext().getInterfaceType(interfce) == InterfaceType.BUSINESS_REMOTE) { |
| |
| IntraVmCopyMonitor.pre(strategy); |
| final ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader(); |
| Thread.currentThread().setContextClassLoader(getBeanContext().getClassLoader()); |
| try { |
| args = copyArgs(args); |
| method = copyMethod(method); |
| interfce = copyObj(interfce); |
| } finally { |
| Thread.currentThread().setContextClassLoader(oldClassLoader); |
| IntraVmCopyMonitor.post(); |
| } |
| |
| } else if (strategy == COPY && args.length > 0) { |
| |
| IntraVmCopyMonitor.pre(strategy); |
| try { |
| args = copyArgs(args); |
| } finally { |
| IntraVmCopyMonitor.post(); |
| } |
| } |
| |
| final IntraVmCopyMonitor.State oldStrategy = strategy; |
| if (getBeanContext().isAsynchronous(method) || getBeanContext().getComponentType().equals(BeanType.MANAGED)) { |
| strategy = NONE; |
| } |
| |
| try { |
| |
| final Object returnValue = _invoke(proxy, interfce, method, args); |
| return copy(strategy, returnValue); |
| } catch (Throwable throwable) { |
| throwable = copy(strategy, throwable); |
| throw convertException(throwable, method, interfce); |
| } finally { |
| strategy = oldStrategy; |
| } |
| } finally { |
| |
| if (callContext == null && localClientIdentity != null) { |
| final SecurityService securityService = SystemInstance.get().getComponent(SecurityService.class); |
| if(null != securityService){ |
| securityService.disassociate(); |
| } |
| } |
| } |
| } |
| |
| private <T> T copy(final IntraVmCopyMonitor.State strategy, final T object) throws IOException, ClassNotFoundException { |
| if (object == null || !strategy.isCopy()) { |
| return object; |
| } |
| |
| IntraVmCopyMonitor.pre(strategy); |
| try { |
| return copyObj(object); |
| } finally { |
| IntraVmCopyMonitor.post(); |
| } |
| } |
| |
| public boolean isValid() { |
| return !isInvalidReference; |
| } |
| |
| private void isValidReference(final Method method) throws NoSuchObjectException { |
| if (isInvalidReference) { |
| if (interfaceType.isComponent() && interfaceType.isLocal()) { |
| throw new NoSuchObjectLocalException("reference is invalid"); |
| } else if (interfaceType.isComponent() || Remote.class.isAssignableFrom(method.getDeclaringClass())) { |
| throw new NoSuchObjectException("reference is invalid"); |
| } else { |
| throw new NoSuchEJBException("reference is invalid for " + deploymentID); |
| } |
| } |
| if (!(Object.class.equals(method.getDeclaringClass()) |
| && method.getName().equals("finalize") |
| && method.getExceptionTypes().length == 1 |
| && Throwable.class.equals(method.getExceptionTypes()[0]))) { |
| getBeanContext(); // will throw an exception if app has been undeployed. |
| } |
| } |
| |
| /** |
| * Renamed method so it shows up with a much more understandable purpose as it |
| * will be the top element in the stacktrace |
| * |
| * @param e Throwable |
| * @param method Method |
| * @param interfce Class |
| */ |
| protected Throwable convertException(Throwable e, final Method method, final Class interfce) { |
| final boolean rmiRemote = Remote.class.isAssignableFrom(interfce); |
| if (e instanceof TransactionRequiredException) { |
| if (!rmiRemote && interfaceType.isBusiness()) { |
| return new EJBTransactionRequiredException(e.getMessage()).initCause(getCause(e)); |
| } else if (interfaceType.isLocal()) { |
| return new TransactionRequiredLocalException(e.getMessage()).initCause(getCause(e)); |
| } else { |
| return e; |
| } |
| } |
| if (e instanceof TransactionRolledbackException) { |
| if (!rmiRemote && interfaceType.isBusiness()) { |
| return new EJBTransactionRolledbackException(e.getMessage()).initCause(getCause(e)); |
| } else if (interfaceType.isLocal()) { |
| return new TransactionRolledbackLocalException(e.getMessage()).initCause(getCause(e)); |
| } else { |
| return e; |
| } |
| } |
| if (e instanceof NoSuchObjectException) { |
| if (!rmiRemote && interfaceType.isBusiness()) { |
| return new NoSuchEJBException(e.getMessage()).initCause(getCause(e)); |
| } else if (interfaceType.isLocal()) { |
| return new NoSuchObjectLocalException(e.getMessage()).initCause(getCause(e)); |
| } else { |
| return e; |
| } |
| } |
| if (e instanceof AccessException) { |
| if (!rmiRemote && interfaceType.isBusiness()) { |
| return new AccessLocalException(e.getMessage()).initCause(getCause(e)); |
| } else if (interfaceType.isLocal()) { |
| return new AccessLocalException(e.getMessage()).initCause(getCause(e)); |
| } else { |
| return e; |
| } |
| } |
| if (e instanceof RemoteException) { |
| if (!rmiRemote && interfaceType.isBusiness()) { |
| return new EJBException(e.getMessage()).initCause(getCause(e)); |
| } else if (interfaceType.isLocal()) { |
| return new EJBException(e.getMessage()).initCause(getCause(e)); |
| } else { |
| return e; |
| } |
| } |
| |
| for (final Class<?> type : method.getExceptionTypes()) { |
| if (type.isAssignableFrom(e.getClass())) { |
| return e; |
| } |
| } |
| |
| // Exception is undeclared |
| // Try and find a runtime exception in there |
| while (e.getCause() != null && !(e instanceof RuntimeException)) { |
| e = e.getCause(); |
| } |
| return e; |
| } |
| |
| /** |
| * Method instance on proxies that come from a classloader outside |
| * the bean's classloader need to be swapped out for the identical |
| * method in the bean's classloader. |
| * |
| * @param method Method |
| * @return return's the same method but loaded from the beans classloader |
| */ |
| |
| private Method copyMethod(final Method method) throws Exception { |
| final int parameterCount = method.getParameterTypes().length; |
| Class[] types = new Class[1 + parameterCount]; |
| types[0] = method.getDeclaringClass(); |
| System.arraycopy(method.getParameterTypes(), 0, types, 1, parameterCount); |
| |
| types = (Class[]) copyArgs(types); |
| |
| final Class targetClass = types[0]; |
| final Class[] targetParameters = new Class[parameterCount]; |
| System.arraycopy(types, 1, targetParameters, 0, parameterCount); |
| return targetClass.getMethod(method.getName(), targetParameters); |
| } |
| |
| protected Throwable getCause(final Throwable e) { |
| if (e != null && e.getCause() != null) { |
| return e.getCause(); |
| } |
| return e; |
| } |
| |
| public String toString() { |
| String name = null; |
| try { |
| name = getProxyInfo().getInterface().getName(); |
| } catch (final Exception e) { |
| //Ignore |
| } |
| return "proxy=" + name + ";deployment=" + this.deploymentID + ";pk=" + this.primaryKey; |
| } |
| |
| public int hashCode() { |
| if (primaryKey == null) { |
| |
| return deploymentID.hashCode(); |
| } else { |
| return primaryKey.hashCode(); |
| } |
| } |
| |
| @SuppressWarnings("EqualsWhichDoesntCheckParameterClass") |
| public boolean equals(Object obj) { |
| if (obj == null) { |
| return false; |
| } |
| if (this == obj) { |
| return true; |
| } |
| if (!BaseEjbProxyHandler.class.isInstance(obj)) { |
| final Class<?> aClass = obj.getClass(); |
| if (Proxy.isProxyClass(aClass)) { |
| obj = Proxy.getInvocationHandler(obj); |
| } else if (LocalBeanProxyFactory.isProxy(aClass)) { |
| obj = LocalBeanProxyFactory.getInvocationHandler(obj); |
| } else { |
| return false; |
| } |
| } |
| final BaseEjbProxyHandler other = (BaseEjbProxyHandler) obj; |
| return equalHandler(other); |
| } |
| |
| protected boolean equalHandler(final BaseEjbProxyHandler other) { |
| return (primaryKey == null ? other.primaryKey == null : primaryKey.equals(other.primaryKey)) |
| && deploymentID.equals(other.deploymentID) |
| && getMainInterface().equals(other.getMainInterface()); |
| } |
| |
| protected abstract Object _invoke(Object proxy, Class interfce, Method method, Object[] args) throws Throwable; |
| |
| protected Object[] copyArgs(final Object[] objects) throws IOException, ClassNotFoundException { |
| if (objects == null) { |
| return null; |
| } |
| /* |
| while copying the arguments is necessary. Its not necessary to copy the array itself, |
| because they array is created by the Proxy implementation for the sole purpose of |
| packaging the arguments for the InvocationHandler.invoke( ) method. Its ephemeral |
| and their for doesn't need to be copied. |
| */ |
| |
| for (int i = 0; i < objects.length; i++) { |
| objects[i] = copyObj(objects[i]); |
| } |
| |
| return objects; |
| } |
| |
| /* change dereference to copy */ |
| protected <T> T copyObj(final T object) throws IOException, ClassNotFoundException { |
| // Check for primitive and other known class types that are immutable. If detected |
| // we can safely return them. |
| if (object == null) { |
| return null; |
| } |
| final Class ooc = object.getClass(); |
| if (ooc == int.class || |
| ooc == String.class || |
| ooc == long.class || |
| ooc == boolean.class || |
| ooc == byte.class || |
| ooc == float.class || |
| ooc == double.class || |
| ooc == short.class || |
| ooc == Long.class || |
| ooc == Boolean.class || |
| ooc == Byte.class || |
| ooc == Character.class || |
| ooc == Float.class || |
| ooc == Double.class || |
| ooc == Short.class || |
| ooc == BigDecimal.class) { |
| return object; |
| } |
| |
| final ByteArrayOutputStream baos = new ByteArrayOutputStream(128); |
| try { |
| final ObjectOutputStream out = new ObjectOutputStream(baos); |
| out.writeObject(object); |
| out.close(); |
| } catch (final NotSerializableException e) { |
| throw (IOException) new NotSerializableException(e.getMessage() + |
| " : The EJB specification restricts remote interfaces to only serializable data types. This can be disabled for in-vm use with the " + |
| OPENEJB_LOCALCOPY + |
| "=false system property.").initCause(e); |
| } |
| |
| final ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); |
| final ObjectInputStream in = new EjbObjectInputStream(bais); |
| final Object obj = in.readObject(); |
| return (T) obj; |
| } |
| |
| public void invalidateReference() { |
| this.container = null; |
| this.setBeanContext(null); |
| this.isInvalidReference = true; |
| } |
| |
| protected void invalidateAllHandlers(final Object key) { |
| final HashSet<BaseEjbProxyHandler> set = (HashSet) getLiveHandleRegistry().remove(key); |
| if (set == null) { |
| return; |
| } |
| |
| final ReentrantLock l = lock; |
| l.lock(); |
| |
| try { |
| for (final BaseEjbProxyHandler handler : set) { |
| handler.invalidateReference(); |
| } |
| } finally { |
| l.unlock(); |
| } |
| } |
| |
| protected abstract Object _writeReplace(Object proxy) throws ObjectStreamException; |
| |
| protected void registerHandler(final Object key, final BaseEjbProxyHandler handler) { |
| Set set = (Set) getLiveHandleRegistry().get(key); |
| if (set == null) { |
| set = new HashSet(); |
| final Object existing = getLiveHandleRegistry().putIfAbsent(key, set); |
| if (existing != null) { |
| set = Set.class.cast(existing); |
| } |
| } |
| final ReentrantLock l = lock; |
| l.lock(); |
| try { |
| set.add(handler); |
| } finally { |
| l.unlock(); |
| } |
| } |
| |
| public abstract ProxyInfo getProxyInfo(); |
| |
| public BeanContext getBeanContext() { |
| final BeanContext beanContext = beanContextRef.get(); |
| if (beanContext == null || beanContext.isDestroyed()) { |
| try { |
| invalidateReference(); |
| } catch (final IllegalStateException e) { |
| //no-op, as we are about to throw a better reason |
| } |
| throw new IllegalStateException("Bean '" + deploymentID + "' has been undeployed."); |
| } |
| return beanContext; |
| } |
| |
| public void setBeanContext(final BeanContext beanContext) { |
| this.beanContextRef = new WeakReference<BeanContext>(beanContext); |
| } |
| |
| public ConcurrentMap getLiveHandleRegistry() { |
| final BeanContext beanContext = getBeanContext(); |
| ProxyRegistry proxyRegistry = beanContext.get(ProxyRegistry.class); |
| if (proxyRegistry == null) { |
| proxyRegistry = new ProxyRegistry(); |
| beanContext.set(ProxyRegistry.class, proxyRegistry); |
| } |
| return proxyRegistry.liveHandleRegistry; |
| } |
| |
| private void writeObject(final ObjectOutputStream out) throws IOException { |
| out.defaultWriteObject(); |
| |
| out.writeObject(getInterfaces()); |
| out.writeObject(getMainInterface()); |
| } |
| |
| private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException { |
| |
| in.defaultReadObject(); |
| |
| final ContainerSystem containerSystem = SystemInstance.get().getComponent(ContainerSystem.class); |
| |
| if(null == containerSystem){ |
| throw new OpenEJBRuntimeException("ContainerSystem has not been initialized"); |
| } |
| |
| setBeanContext(containerSystem.getBeanContext(deploymentID)); |
| container = (RpcContainer) getBeanContext().getContainer(); |
| |
| if (IntraVmCopyMonitor.isCrossClassLoaderOperation()) { |
| setDoCrossClassLoaderCopy(true); |
| } |
| |
| setInterfaces((List<Class>) in.readObject()); |
| setMainInterface((Class) in.readObject()); |
| } |
| |
| private static class ProxyRegistry { |
| |
| protected final ConcurrentMap liveHandleRegistry = new ConcurrentHashMap(); |
| } |
| } |