diff options
Diffstat (limited to 'src/main/javassist/bytecode/BootstrapMethodsAttribute.java')
-rw-r--r-- | src/main/javassist/bytecode/BootstrapMethodsAttribute.java | 103 |
1 files changed, 81 insertions, 22 deletions
diff --git a/src/main/javassist/bytecode/BootstrapMethodsAttribute.java b/src/main/javassist/bytecode/BootstrapMethodsAttribute.java index 94a0481f..0fd04cf8 100644 --- a/src/main/javassist/bytecode/BootstrapMethodsAttribute.java +++ b/src/main/javassist/bytecode/BootstrapMethodsAttribute.java @@ -2,6 +2,7 @@ package javassist.bytecode; import java.io.DataInputStream; import java.io.IOException; +import java.util.Arrays; import java.util.Map; public class BootstrapMethodsAttribute extends AttributeInfo { @@ -35,6 +36,26 @@ public class BootstrapMethodsAttribute extends AttributeInfo { * <code>bootstrap_arguments</code>. */ public int[] arguments; + + /** + * Makes a copy. Class names are replaced according to the + * * given <code>Map</code> object. + * + * @param srcCp the constant pool table from the source + * @param destCp the constant pool table used bt new copy + * @param classnames pairs of replaced and substituted class names. + * + * @return new BootstrapMethod + */ + protected BootstrapMethod copy(ConstPool srcCp, ConstPool destCp, Map<String,String> classnames) { + int newMethodRef = srcCp.copy(methodRef, destCp, classnames); + int[] newArguments = new int[arguments.length]; + + for (int i = 0; i < arguments.length; i++) + newArguments[i] = srcCp.copy(arguments[i], destCp, classnames); + + return new BootstrapMethod(newMethodRef, newArguments); + } } BootstrapMethodsAttribute(ConstPool cp, int n, DataInputStream in) @@ -51,25 +72,8 @@ public class BootstrapMethodsAttribute extends AttributeInfo { */ public BootstrapMethodsAttribute(ConstPool cp, BootstrapMethod[] methods) { super(cp, tag); - int size = 2; - for (int i = 0; i < methods.length; i++) - size += 4 + methods[i].arguments.length * 2; - - byte[] data = new byte[size]; - ByteArray.write16bit(methods.length, data, 0); // num_bootstrap_methods - int pos = 2; - for (int i = 0; i < methods.length; i++) { - ByteArray.write16bit(methods[i].methodRef, data, pos); - ByteArray.write16bit(methods[i].arguments.length, data, pos + 2); - int[] args = methods[i].arguments; - pos += 4; - for (int k = 0; k < args.length; k++) { - ByteArray.write16bit(args[k], data, pos); - pos += 2; - } - } - set(data); + set(convertMethodsToBytes(methods)); } /** @@ -113,12 +117,67 @@ public class BootstrapMethodsAttribute extends AttributeInfo { BootstrapMethod[] methods = getMethods(); ConstPool thisCp = getConstPool(); for (int i = 0; i < methods.length; i++) { - BootstrapMethod m = methods[i]; - m.methodRef = thisCp.copy(m.methodRef, newCp, classnames); - for (int k = 0; k < m.arguments.length; k++) - m.arguments[k] = thisCp.copy(m.arguments[k], newCp, classnames); + methods[i] = methods[i].copy(thisCp, newCp, classnames); } return new BootstrapMethodsAttribute(newCp, methods); } + + /** + * add bootstrap method from given <code>ConstPool</code> and <code>BootstrapMethod</code>, + * and add it to the specified index. Class names are replaced according to the + * given <code>Map</code> object. + * + * <p> + * if the index less than 0 or large than the origin method length, then throw <code>RuntimeException</code>;<br> + * if the index large or equals to 0 and less or equals to the origin method length, + * then replace the origin method with the new <code>BootstrapMethod srcBm</code> ;<br> + * if the index equals to the origin method length, then append the new <code>BootstrapMethod srcBm</code> at + * the origin methods tail. + * </p> + * + * @param srcCp the constant pool table of source. + * @param srcBm the bootstrap method of source + * @param index the new method index on bootstrap methods + * @param classnames pairs of replaced and substituted + * class names. + */ + public void addMethod(ConstPool srcCp, BootstrapMethod srcBm, int index, Map<String,String> classnames) { + BootstrapMethod[] methods = getMethods(); + + if (index < 0 || index > methods.length) { + throw new RuntimeException("index out of range"); + } + + if (index == methods.length) { + BootstrapMethod[] newBmArray = new BootstrapMethod[methods.length + 1]; + System.arraycopy(methods, 0, newBmArray, 0, methods.length); + methods = newBmArray; + } + + methods[index] = srcBm.copy(srcCp, getConstPool(), classnames); + set(convertMethodsToBytes(methods)); + } + + private static byte[] convertMethodsToBytes(BootstrapMethod[] methods) { + int size = 2; + for (int i = 0; i < methods.length; i++) + size += 4 + methods[i].arguments.length * 2; + + byte[] data = new byte[size]; + ByteArray.write16bit(methods.length, data, 0); // num_bootstrap_methods + int pos = 2; + for (int i = 0; i < methods.length; i++) { + ByteArray.write16bit(methods[i].methodRef, data, pos); + ByteArray.write16bit(methods[i].arguments.length, data, pos + 2); + int[] args = methods[i].arguments; + pos += 4; + for (int k = 0; k < args.length; k++) { + ByteArray.write16bit(args[k], data, pos); + pos += 2; + } + } + + return data; + } } |