in proxy/proxy-impl/src/main/java/org/apache/aries/proxy/impl/AsmProxyManager.java [49:145]
public Object createNewProxy(Bundle clientBundle, Collection<Class<?>> classes,
Callable<Object> dispatcher, InvocationListener listener) throws UnableToProxyException
{
Object proxyObject = null;
// if we just have interfaces and no classes we default to using
// the interface proxy because we can't dynamically
// subclass more than one interface
// unless we have a class
// that implements all of them
// loop through the classes checking if they are java interfaces
// if we find any class that isn't an interface we need to use
// the subclass proxy
Set<Class<?>> notInterfaces = new HashSet<Class<?>>();
Set<Class<?>> interfaces = new HashSet<Class<?>>();
for (Class<?> clazz : classes) {
if (!clazz.isInterface()) {
notInterfaces.add(clazz);
} else {
interfaces.add(clazz);
}
}
// if we just have no classes we default to using
// the interface proxy because we can't dynamically
// subclass more than one interface
// unless we have a class
// that implements all of them
if (notInterfaces.isEmpty()) {
proxyObject = InterfaceProxyGenerator.getProxyInstance(clientBundle, null, interfaces, dispatcher, listener);
} else {
// if we need to use the subclass proxy then we need to find
// the most specific class
Class<?> classToProxy = getLowestSubclass(notInterfaces);
if(WovenProxy.class.isAssignableFrom(classToProxy)) {
if(isConcrete(classToProxy) && implementsAll(classToProxy, interfaces)) {
try {
Constructor<?> c = classToProxy.getDeclaredConstructor(Callable.class,
InvocationListener.class);
c.setAccessible(true);
proxyObject = c.newInstance(dispatcher, listener);
} catch (Exception e) {
//We will have to subclass this one, but we should always have a constructor
//to use
//TODO log that performance would be improved by using a non-null template
}
} else {
//We need to generate a class that implements the interfaces (if any) and
//has the classToProxy as a superclass
if((classToProxy.getModifiers() & Modifier.FINAL) != 0) {
throw new UnableToProxyException(classToProxy, "The class " + classToProxy
+ " does not implement all of the interfaces " + interfaces +
" and is final. This means that we cannot create a proxy for both the class and all of the requested interfaces.");
}
proxyObject = InterfaceProxyGenerator.getProxyInstance(clientBundle,
classToProxy, interfaces, dispatcher, listener);
}
}
if(proxyObject == null){
// ARIES-1216 : in some cases, some class can not be visible from the root class classloader.
// If that's the case, we need to build a custom classloader that has visibility on all those classes
// If we could generate a proper constructor this would not be necessary, but since we have to rely
// on the generated serialization constructor to bypass the JVM verifier, we don't have much choice
ClassLoader classLoader = classToProxy.getClassLoader();
if (classLoader == null) {
classLoader = bootClassLoader;
}
boolean allVisible = true;
for (Class<?> clazz : classes) {
try {
if (classLoader.loadClass(clazz.getName()) != clazz) {
throw new UnableToProxyException(classToProxy, "The requested class " + clazz + " is different from the one seen by by " + classToProxy);
}
} catch (ClassNotFoundException e) {
allVisible = false;
break;
}
}
if (!allVisible) {
List<ClassLoader> classLoaders = new ArrayList<ClassLoader>();
for (Class<?> clazz : classes) {
ClassLoader cl = clazz.getClassLoader();
if (cl != null && !classLoaders.contains(cl)) {
classLoaders.add(cl);
}
}
classLoader = new MultiClassLoader(classLoaders);
}
proxyObject = ProxySubclassGenerator.newProxySubclassInstance(classToProxy, classLoader, new ProxyHandler(this, dispatcher, listener));
}
}
return proxyObject;
}