Skip to content

Commit

Permalink
Successfully proxy full duplex ClassLoader linkage
Browse files Browse the repository at this point in the history
  • Loading branch information
lincolnthree committed Jan 4, 2013
1 parent 2655d5a commit 0e5e62b
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 41 deletions.
13 changes: 0 additions & 13 deletions se/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,6 @@
<outputDirectory>${project.build.outputDirectory}/bootpath</outputDirectory>
</configuration>
</execution>
<execution>
<id>src-dependencies</id>
<phase>package</phase>
<goals>
<!-- use copy-dependencies instead if you don't want to explode the sources -->
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<classifier>sources</classifier>
<failOnMissingClassifierArtifact>false</failOnMissingClassifierArtifact>
<outputDirectory>${project.build.directory}/sources</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;

import javassist.util.proxy.MethodFilter;
import javassist.util.proxy.MethodHandler;
Expand All @@ -15,6 +16,7 @@

import org.jboss.forge.container.exception.ContainerException;
import org.jboss.forge.container.util.Arrays;
import org.jboss.forge.container.util.ClassLoaders;

public class ClassLoaderAdapterCallback implements MethodHandler
{
Expand All @@ -33,54 +35,71 @@ public ClassLoaderAdapterCallback(ClassLoader fromLoader, ClassLoader toLoader,
public Object invoke(final Object obj, final Method proxy, final Method method, final Object[] args)
throws Throwable
{
try
return ClassLoaders.executeIn(toLoader, new Callable<Object>()
{
List<Class<?>> parameterTypes = convertParameterTypes(proxy);
@Override
public Object call() throws Exception
{
try
{
List<Class<?>> parameterTypes = convertParameterTypes(proxy);

Method delegateMethod = delegate.getClass().getMethod(proxy.getName(),
parameterTypes.toArray(new Class<?>[parameterTypes.size()]));
Method delegateMethod = delegate.getClass().getMethod(proxy.getName(),
parameterTypes.toArray(new Class<?>[parameterTypes.size()]));

List<Object> parameterValues = convertParameterValues(args, delegateMethod);
List<Object> parameterValues = convertParameterValues(args, delegateMethod);

AccessibleObject.setAccessible(new AccessibleObject[] { delegateMethod }, true);
Object result = delegateMethod.invoke(delegate, parameterValues.toArray());
AccessibleObject.setAccessible(new AccessibleObject[] { delegateMethod }, true);
Object result = delegateMethod.invoke(delegate, parameterValues.toArray());

return enhanceResult(proxy, result);
}
catch (Throwable e)
{
throw new ContainerException(
"Could not invoke proxy method [" + delegate.getClass().getName() + "."
+ proxy.getName() + "()] in ClassLoader ["
+ toLoader + "]", e);
}
return enhanceResult(proxy, result);
}
catch (Throwable e)
{
throw new ContainerException(
"Could not invoke proxy method [" + delegate.getClass().getName() + "."
+ proxy.getName() + "()] in ClassLoader ["
+ toLoader + "]", e);
}
}
});
}

private Object enhanceResult(final Method method, Object result)
{
if (result != null)
{
Class<?> returnType = method.getReturnType();
if (!returnType.isPrimitive() && !Modifier.isFinal(returnType.getModifiers()))
if (needsEnhancement(result))
{
if (Object.class.equals(returnType) && !Object.class.equals(result))
if (!Modifier.isFinal(returnType.getModifiers()))
{
result = enhance(fromLoader, toLoader, method, result,
getObjectClassHierarchy(fromLoader, result));
if (Object.class.equals(returnType) && !Object.class.equals(result))
{
result = enhance(fromLoader, toLoader, method, result,
getObjectClassHierarchy(fromLoader, result));
}
else
{
result = enhance(fromLoader, toLoader, method, result, returnType);
}
}
else
{
result = enhance(fromLoader, toLoader, method, result, returnType);
result = enhance(fromLoader, toLoader, method, getClassHierarchy(fromLoader, returnType));
}
}
else if (Modifier.isFinal(returnType.getModifiers()))
{
result = enhance(fromLoader, toLoader, method, getClassHierarchy(fromLoader, returnType));
}
}
return result;
}

private boolean needsEnhancement(Object object)
{
Class<? extends Object> type = object.getClass();
return !type.getName().contains("java.lang") &&
!type.isPrimitive();
}

private List<Object> convertParameterValues(final Object[] args, Method delegateMethod)
{
List<Object> parameterValues = new ArrayList<Object>();
Expand All @@ -98,7 +117,7 @@ private List<Object> convertParameterValues(final Object[] args, Method delegate
final Class<?> parameterType = parameterValue.getClass();
if (!delegateParameterType.isAssignableFrom(parameterType))
{
Object delegateParameterValue = enhance(toLoader, fromLoader, parameterType,
Object delegateParameterValue = enhance(toLoader, fromLoader, parameterValue,
delegateParameterType);
parameterValues.add(delegateParameterValue);
}
Expand Down Expand Up @@ -232,8 +251,18 @@ public boolean isHandled(Method method)

try
{
((ProxyObject) enhancedResult).setHandler(
new ClassLoaderAdapterCallback(fromLoader, toLoader, delegate));
Class<?>[] interfaces = enhancedResult.getClass().getInterfaces();
for (Class<?> type : interfaces)
{
if (ProxyObject.class.getName().equals(type.getName()))
{
type.getMethod("setHandler", fromLoader.loadClass(MethodHandler.class.getName()))
.invoke(enhancedResult,
fromLoader.loadClass(ClassLoaderAdapterCallback.class.getName()).getConstructors()[0]
.newInstance(fromLoader, toLoader, delegate));
}
}

}
catch (Exception e)
{
Expand Down

0 comments on commit 0e5e62b

Please sign in to comment.