/** 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); } } }
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(); }
/** * 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); } } }
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); } } }