public Object createNewProxy()

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