Пример #1
0
  /**
   * Visit every class/interface this proxy should implement, and generate the appropriate bytecode
   * for delegation if available.
   *
   * @param clazz an class for which to generate bytecode
   */
  private void visitClass(final Class clazz) {
    Method[] methods = clazz.getDeclaredMethods();
    for (Method method : methods) {
      Class<?>[] exceptionTypes = method.getExceptionTypes();
      String[] exceptions = new String[exceptionTypes.length];
      for (int i = 0; i < exceptions.length; i++) {
        exceptions[i] = BytecodeHelper.getClassInternalName(exceptionTypes[i]);
      }
      // for each method defined in the class, generate the appropriate delegation bytecode
      visitMethod(
          method.getModifiers(),
          method.getName(),
          BytecodeHelper.getMethodDescriptor(method.getReturnType(), method.getParameterTypes()),
          null,
          exceptions);
    }
    Constructor[] constructors = clazz.getDeclaredConstructors();
    for (Constructor method : constructors) {
      Class<?>[] exceptionTypes = method.getExceptionTypes();
      String[] exceptions = new String[exceptionTypes.length];
      for (int i = 0; i < exceptions.length; i++) {
        exceptions[i] = BytecodeHelper.getClassInternalName(exceptionTypes[i]);
      }
      // for each method defined in the class, generate the appropriate delegation bytecode
      visitMethod(
          method.getModifiers(),
          "<init>",
          BytecodeHelper.getMethodDescriptor(Void.TYPE, method.getParameterTypes()),
          null,
          exceptions);
    }

    for (Class intf : clazz.getInterfaces()) {
      visitClass(intf);
    }
    Class superclass = clazz.getSuperclass();
    if (superclass != null) visitClass(superclass);

    // Ultimately, methods can be available in the closure map which are not defined by the
    // superclass
    // nor the interfaces
    for (Map.Entry<String, Boolean> entry : delegatedClosures.entrySet()) {
      Boolean visited = entry.getValue();
      if (!visited) {
        String name = entry.getKey();
        if (!"*".equals(name)) {
          // generate a new method
          visitMethod(ACC_PUBLIC, name, "([Ljava/lang/Object;)Ljava/lang/Object;", null, null);
        }
      }
    }
  }