示例#1
0
  /** Main entry for this transformer. */
  public void doTransformInterface(ClassEnhancer ce, ClassGen cg) {
    String class_name = cg.getClassName();
    ConstantPoolGen cpg = cg.getConstantPool();

    checkReadClassAttributes(ce, cg, class_name, cpg);

    generateFieldAccessForCallout(ce, cg, class_name, cpg);

    generateSuperAccessors(ce, cg, class_name, cpg);

    HashSet<String> calloutBindings = CallinBindingManager.getCalloutBindings(class_name);

    if (calloutBindings == null) {
      if (logging) printLogMessage("\nClass " + class_name + " requires no callout adjustment.");
      return;
    }

    if (logging) printLogMessage("\nCallout bindings might be changing class " + class_name + ":");

    HashSet<String> oldStyleBinding = new HashSet<String>();

    // try new style decapsulation first (since 1.2.8):
    for (String calloutBinding : calloutBindings) {
      DecapsulationDescriptor desc = new DecapsulationDescriptor();
      if (!desc.decode(calloutBinding, cg))
        oldStyleBinding.add(calloutBinding); // old style attribute
      else if (!desc.existsAlready) ce.addMethod(desc.generate(class_name, cpg), cg);
    }

    if (oldStyleBinding.isEmpty()) return;

    // --> follows: old style decapsulation for remaining bindings:
    int pos = class_name.lastIndexOf('.');
    String package_name = "NO_PACKAGE";
    if (pos != -1) package_name = class_name.substring(0, pos);

    Method[] methods = cg.getMethods();
    for (int i = 0; i < methods.length; i++) {
      Method m = methods[i];
      String method_name = m.getName();

      boolean requiresAdjustment =
          CallinBindingManager.requiresCalloutAdjustment(
              oldStyleBinding, method_name, m.getSignature());

      if (requiresAdjustment) {
        ce.decapsulateMethod(m, cg, package_name, cpg);
      }
    }
  }
示例#2
0
  private Method generateSuperAccessor(
      ConstantPoolGen cpg,
      String className,
      SuperMethodDescriptor superMethod,
      InstructionFactory factory) {
    int endPos = superMethod.signature.indexOf(')');
    String segment = superMethod.signature.substring(1, endPos);
    String[] typeNames = (segment.length() > 0) ? segment.split(",") : new String[0];
    Type[] argTypes = new Type[typeNames.length];
    for (int i = 0; i < argTypes.length; i++) argTypes[i] = Type.getType(typeNames[i]);

    int index = superMethod.signature.lastIndexOf(')') + 1;
    Type returnType = Type.getType(superMethod.signature.substring(index));

    Type baseType = new ObjectType(className);
    Type[] wrapperTypes = new Type[argTypes.length + 1];
    System.arraycopy(argTypes, 0, wrapperTypes, 1, argTypes.length);
    wrapperTypes[0] = baseType;
    String[] argNames = new String[wrapperTypes.length];
    for (int i = 0; i < argNames.length; i++) {
      argNames[i] = "arg" + i;
    }
    InstructionList il = new InstructionList();
    MethodGen mg =
        new MethodGen(
            (Constants.ACC_PUBLIC | Constants.ACC_STATIC),
            returnType,
            wrapperTypes,
            argNames,
            OT_PREFIX + superMethod.methodName + "$super",
            className,
            il,
            cpg);
    il.append(InstructionFactory.createLoad(baseType, 0)); // first argument is base instance
    for (int i = 0; i < argTypes.length; i++)
      il.append(InstructionFactory.createLoad(argTypes[i], i + 1));

    // if super method is also callin bound directly invoke the orig-version
    // (to avoid that BaseMethodTransformation.checkReplaceWickedSuper() has to rewrite this code
    // again):
    String methodName =
        (CallinBindingManager.isBoundBaseMethod(
                superMethod.superClass, superMethod.methodName, superMethod.signature))
            ? genOrigMethName(superMethod.methodName)
            : superMethod.methodName;

    il.append(
        factory.createInvoke(
            superMethod.superClass, methodName, returnType, argTypes, INVOKESPECIAL));
    il.append(InstructionFactory.createReturn(returnType));
    mg.setMaxStack();
    mg.setMaxLocals();
    return mg.getMethod();
  }
示例#3
0
  /**
   * Generates getter and setter methods for all fields of the class 'class_name' which are accessed
   * via callout. Informations are received via attributs (CallinBindingManager).
   *
   * @param cg the ClassGen of the appropriate class
   * @param class_name the name of the class
   * @param cpg the ConstantPoolGen of the class
   * @param es the ExtensionSet to add the new access methods
   */
  private void generateFieldAccessForCallout(
      ClassEnhancer ce, ClassGen cg, String class_name, ConstantPoolGen cpg) {
    InstructionFactory factory = null;

    HashSet<String> addedAccessMethods = this.generatedFieldCalloutAccessors;

    List<FieldDescriptor> getter = CallinBindingManager.getCalloutGetFields(class_name);
    if (getter != null) {
      factory = new InstructionFactory(cg);
      Iterator<FieldDescriptor> it = getter.iterator();
      while (it.hasNext()) {
        FieldDescriptor fd = it.next();
        String key = "get_" + class_name + "." + fd.getFieldName() + fd.getFieldSignature();
        if (logging) printLogMessage("Generating getter method " + key);
        if (addedAccessMethods == null) addedAccessMethods = new HashSet<String>();
        if (addedAccessMethods.contains(key)) continue; // this getter has already been created
        ce.addMethod(generateGetter(cpg, class_name, fd, factory), cg);
        addedAccessMethods.add(key);
      }
    }

    List<FieldDescriptor> setter = CallinBindingManager.getCalloutSetFields(class_name);
    if (setter != null) {
      if (factory == null) factory = new InstructionFactory(cg);
      Iterator<FieldDescriptor> it = setter.iterator();
      while (it.hasNext()) {
        FieldDescriptor fd = it.next();
        String key = "set_" + class_name + "." + fd.getFieldName() + fd.getFieldSignature();
        if (logging) printLogMessage("Generating setter method " + key);
        if (addedAccessMethods == null) addedAccessMethods = new HashSet<String>();
        if (addedAccessMethods.contains(key)) continue; // this setter has already been created
        ce.addMethod(generateSetter(cpg, class_name, fd, factory), cg);
        addedAccessMethods.add(key);
      }
    }
  }
示例#4
0
  private void generateSuperAccessors(
      ClassEnhancer ce, ClassGen cg, String class_name, ConstantPoolGen cpg) {
    InstructionFactory factory = null;

    HashSet<String> addedAccessMethods = this.generatedSuperAccessors;

    List<SuperMethodDescriptor> methods = CallinBindingManager.getSuperAccesses(class_name);
    if (methods != null) {
      factory = new InstructionFactory(cg);
      for (SuperMethodDescriptor superMethod : methods) {
        String key = superMethod.methodName + '.' + superMethod.signature;
        if (logging) printLogMessage("Generating super access method " + key);
        if (addedAccessMethods == null) addedAccessMethods = new HashSet<String>();
        if (addedAccessMethods.contains(key)) continue; // this accessor has already been created
        ce.addMethod(generateSuperAccessor(cpg, class_name, superMethod, factory), cg);
        addedAccessMethods.add(key);
      }
    }
  }