Author: ron.sigal(a)jboss.com
Date: 2008-02-22 04:36:22 -0500 (Fri, 22 Feb 2008)
New Revision: 3471
Modified:
remoting2/branches/2.x/src/main/org/jboss/remoting/MicroRemoteClientInvoker.java
Log:
JBREM-900: Introduced a WeakHashMap of unmarshallers.
Modified:
remoting2/branches/2.x/src/main/org/jboss/remoting/MicroRemoteClientInvoker.java
===================================================================
---
remoting2/branches/2.x/src/main/org/jboss/remoting/MicroRemoteClientInvoker.java 2008-02-21
18:17:50 UTC (rev 3470)
+++
remoting2/branches/2.x/src/main/org/jboss/remoting/MicroRemoteClientInvoker.java 2008-02-22
09:36:22 UTC (rev 3471)
@@ -7,13 +7,16 @@
import org.jboss.remoting.marshal.MarshalFactory;
import org.jboss.remoting.marshal.Marshaller;
import org.jboss.remoting.marshal.UnMarshaller;
+import org.jboss.remoting.marshal.UpdateableClassloaderUnMarshaller;
import org.jboss.remoting.transport.ClientInvoker;
import org.jboss.util.id.GUID;
import java.io.IOException;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.WeakHashMap;
/**
* MicroRemoteClientInvoker is an abstract client part handler that implements the bulk
of the heavy
@@ -37,7 +40,7 @@
protected boolean connected = false;
private Marshaller marshaller;
- private UnMarshaller unmarshaller;
+ private Map unmarshallers = new WeakHashMap();
private String dataType;
private final Object clientLeaseLock = new Object();
private LeasePinger leasePinger = null;
@@ -65,9 +68,8 @@
if (trace) { log.trace(this + "(" + (++invokeCount) + ") invoking
" + invocationReq); }
+ // Set up marshaller.
Marshaller marshaller = getMarshaller();
- UnMarshaller unmarshaller = getUnMarshaller();
-
if (marshaller == null)
{
// try by locator (in case marshaller class name specified)
@@ -80,34 +82,61 @@
{
// went as far as possible to find a marshaller, will have to give up
throw new InvalidMarshallingResource(
- "Can not find a valid marshaller for data type: " +
getDataType());
+ "Can not find a valid marshaller for data type: " +
getDataType());
}
- setMarshaller(marshaller);
}
+ setMarshaller(marshaller);
}
- if (unmarshaller == null)
+ // Set up unmarshaller.
+ UnMarshaller unmarshaller = null;
+ RemotingClassLoader rcl = null;
+ synchronized (unmarshallers)
{
- // creating a new classloader containing the remoting class loader (for remote
classloading)
- // and the current thread's class loader. This allows to load remoting
classes as well as
- // user's classes.
- ClassLoader remotingClassLoader =
- new RemotingClassLoader(getClassLoader(),
Thread.currentThread().getContextClassLoader());
-
- // try by locator (in case unmarshaller class name specified)
- unmarshaller = MarshalFactory.getUnMarshaller(getLocator(), getClassLoader());
+ unmarshaller = getUnMarshaller();
if (unmarshaller == null)
{
- unmarshaller = MarshalFactory.getUnMarshaller(getDataType(),
getSerializationType());
+ // try by locator (in case unmarshaller class name specified)
+ unmarshaller = MarshalFactory.getUnMarshaller(getLocator(),
getClassLoader());
if (unmarshaller == null)
{
- // went as far as possible to find a unmarshaller, will have to give up
- throw new InvalidMarshallingResource(
- "Can not find a valid unmarshaller for data type: " +
getDataType());
+ unmarshaller = MarshalFactory.getUnMarshaller(getDataType(),
getSerializationType());
+ if (unmarshaller == null)
+ {
+ // went as far as possible to find a unmarshaller, will have to give
up
+ throw new InvalidMarshallingResource(
+ "Can not find a valid unmarshaller for data type: " +
getDataType());
+ }
}
setUnMarshaller(unmarshaller);
}
- unmarshaller.setClassLoader(remotingClassLoader);
+
+ // Each unmarshaller gets a RemotingClassloader classloader containing the
+ // remoting class loader (for remote classloading) and the current thread's
+ // class loader. This allows to load remoting classes as well as user's
+ // classes. If possible, will simply reset context classloader on existing
+ // RemotingClassLoader.
+ ClassLoader contextClassLoader =
Thread.currentThread().getContextClassLoader();
+ if (unmarshaller instanceof UpdateableClassloaderUnMarshaller)
+ {
+ UpdateableClassloaderUnMarshaller uclum = (UpdateableClassloaderUnMarshaller)
unmarshaller;
+ ClassLoader cl = uclum.getClassLoader();
+ if (cl instanceof RemotingClassLoader)
+ {
+ rcl = (RemotingClassLoader) cl;
+ rcl.setUserClassLoader(contextClassLoader);
+ }
+ else
+ {
+ rcl = new RemotingClassLoader(getClassLoader(), contextClassLoader);
+ unmarshaller.setClassLoader(rcl);
+ }
+ }
+ else
+ {
+ rcl = new RemotingClassLoader(getClassLoader(), contextClassLoader);
+ unmarshaller.setClassLoader(rcl);
+ }
}
// if raw, then send only param of invocation request
@@ -122,9 +151,17 @@
payload = invocationReq;
}
- returnValue =
- transport(invocationReq.getSessionId(), payload, metadata, marshaller,
unmarshaller);
-
+ try
+ {
+ String sessionId = invocationReq.getSessionId();
+ returnValue = transport(sessionId, payload, metadata, marshaller,
unmarshaller);
+ }
+ finally
+ {
+ // Delete reference to current thread's context classloader.
+ rcl.unsetUserClassLoader();
+ }
+
// Now check if is remoting response and process
if (returnValue instanceof InvocationResponse)
{
@@ -313,12 +350,18 @@
public void setUnMarshaller(UnMarshaller unmarshaller)
{
- this.unmarshaller = unmarshaller;
+ synchronized (unmarshallers)
+ {
+ unmarshallers.put(Thread.currentThread().getContextClassLoader(),
unmarshaller);
+ }
}
public UnMarshaller getUnMarshaller()
{
- return this.unmarshaller;
+ synchronized (unmarshallers)
+ {
+ return
(UnMarshaller)unmarshallers.get(Thread.currentThread().getContextClassLoader());
+ }
}
public String getSessionId()