package scouter.javassist.bytecode;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.Map;
import scouter.javassist.bytecode.AttributeInfo;
import scouter.javassist.bytecode.ByteArray;
import scouter.javassist.bytecode.ConstPool;
public class BootstrapMethodsAttribute extends AttributeInfo {
/**
* The name of this attribute <code>"BootstrapMethods"</code>.
*/
public static final String tag = "BootstrapMethods";
/**
* An element of <code>bootstrap_methods</code>.
*/
public static class BootstrapMethod {
/**
* Constructs an element of <code>bootstrap_methods</code>.
*
* @param method <code>bootstrap_method_ref</code>.
* @param args <code>bootstrap_arguments</code>.
*/
public BootstrapMethod(int method, int[] args) {
methodRef = method;
arguments = args;
}
/**
* <code>bootstrap_method_ref</code>.
* The value at this index must be a <code>CONSTANT_MethodHandle_info</code>.
*/
public int methodRef;
/**
* <code>bootstrap_arguments</code>.
*/
public int[] arguments;
}
BootstrapMethodsAttribute(ConstPool cp, int n, DataInputStream in)
throws IOException
{
super(cp, n, in);
}
/**
* Constructs a BootstrapMethods attribute.
*
* @param cp a constant pool table.
* @param methods the contents.
*/
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);
}
/**
* Obtains <code>bootstrap_methods</code> in this attribute.
*
* @return an array of <code>BootstrapMethod</code>. Since it
* is a fresh copy, modifying the returned array does not
* affect the original contents of this attribute.
*/
public BootstrapMethod[] getMethods() {
byte[] data = this.get();
int num = ByteArray.readU16bit(data, 0);
BootstrapMethod[] methods = new BootstrapMethod[num];
int pos = 2;
for (int i = 0; i < num; i++) {
int ref = ByteArray.readU16bit(data, pos);
int len = ByteArray.readU16bit(data, pos + 2);
int[] args = new int[len];
pos += 4;
for (int k = 0; k < len; k++) {
args[k] = ByteArray.readU16bit(data, pos);
pos += 2;
}
methods[i] = new BootstrapMethod(ref, args);
}
return methods;
}
/**
* Makes a copy. Class names are replaced according to the
* given <code>Map</code> object.
*
* @param newCp the constant pool table used by the new copy.
* @param classnames pairs of replaced and substituted
* class names.
*/
public AttributeInfo copy(ConstPool newCp, Map classnames) {
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);
}
return new BootstrapMethodsAttribute(newCp, methods);
}
}