CheckCodeAdapterpublic class CheckCodeAdapter extends CodeAdapter A {@link CodeAdapter CodeAdapter} that checks that its methods are properly
used. More precisely this code adapter checks each instruction individually
(i.e., each visit method checks some preconditions based only on its
arguments - such as the fact that the given opcode is correct for a given
visit method), but does not check the sequence of instructions.
For example, in a method whose signature is void m (), the invalid
instruction IRETURN, or the invalid sequence IADD L2I will not be
detected by this code adapter. |
Fields Summary |
---|
private boolean | endtrue if the visitMaxs method has been called. | private HashMap | labelsThe already visited labels. This map associate Integer values to Label
keys. | private static final int[] | TYPECode of the visit method to be used for each opcode. |
Constructors Summary |
---|
public CheckCodeAdapter(CodeVisitor cv)Constructs a new {@link CheckCodeAdapter CheckCodeAdapter} object.
super(cv);
this.labels = new HashMap();
|
Methods Summary |
---|
static void | checkConstant(java.lang.Object cst)Checks that the given value is an {@link java.lang.Integer Integer}, a
{@link java.lang.Float Float}, a {@link java.lang.Long Long}, a {@link
java.lang.Double Double} or a {@link String String}.
if (!(cst instanceof Integer) &&
!(cst instanceof Float) &&
!(cst instanceof Long) &&
!(cst instanceof Double) &&
!(cst instanceof String))
{
throw new IllegalArgumentException("Invalid constant: " + cst);
}
| static void | checkDesc(java.lang.String desc, boolean canBeVoid)Checks that the given string is a valid type descriptor.
int end = checkDesc(desc, 0, canBeVoid);
if (end != desc.length()) {
throw new IllegalArgumentException("Invalid descriptor: " + desc);
}
| static int | checkDesc(java.lang.String desc, int start, boolean canBeVoid)Checks that a the given substring is a valid type descriptor.
if (desc == null || start >= desc.length()) {
throw new IllegalArgumentException(
"Invalid type descriptor (must not be null or empty)");
}
int index;
switch (desc.charAt(start)) {
case 'V":
if (canBeVoid) {
return start + 1;
} else {
throw new IllegalArgumentException("Invalid descriptor: " + desc);
}
case 'Z":
case 'C":
case 'B":
case 'S":
case 'I":
case 'F":
case 'J":
case 'D":
return start + 1;
case '[":
index = start + 1;
while (index < desc.length() && desc.charAt(index) == '[") {
++index;
}
if (index < desc.length()) {
return checkDesc(desc, index, false);
} else {
throw new IllegalArgumentException("Invalid descriptor: " + desc);
}
case 'L":
index = desc.indexOf(';", start);
if (index == -1 || index - start < 2) {
throw new IllegalArgumentException("Invalid descriptor: " + desc);
}
try {
checkInternalName(desc, start + 1, index, null);
} catch (IllegalArgumentException _) {
throw new IllegalArgumentException("Invalid descriptor: " + desc);
}
return index + 1;
default:
throw new IllegalArgumentException("Invalid descriptor: " + desc);
}
| void | checkEnd()Checks that the visitMaxs method has not been called.
if (end) {
throw new IllegalStateException(
"Cannot visit instructions after visitMaxs has been called.");
}
| static void | checkIdentifier(java.lang.String name, java.lang.String msg)Checks that the given string is a valid Java identifier.
checkIdentifier(name, 0, -1, msg);
| static void | checkIdentifier(java.lang.String name, int start, int end, java.lang.String msg)Checks that the given substring is a valid Java identifier.
if (name == null || (end == -1 ? name.length() <= start : end <= start)) {
throw new IllegalArgumentException(
"Invalid " + msg + " (must not be null or empty)");
}
if (!Character.isJavaIdentifierStart(name.charAt(start))) {
throw new IllegalArgumentException(
"Invalid " + msg + " (must be a valid Java identifier): " + name);
}
int max = (end == -1 ? name.length() : end);
for (int i = start + 1; i < max; ++i) {
if (!Character.isJavaIdentifierPart(name.charAt(i))) {
throw new IllegalArgumentException(
"Invalid " + msg + " (must be a valid Java identifier): " + name);
}
}
| static void | checkInternalName(java.lang.String name, java.lang.String msg)Checks that the given string is a valid internal class name.
checkInternalName(name, 0, -1, msg);
| static void | checkInternalName(java.lang.String name, int start, int end, java.lang.String msg)Checks that the given substring is a valid internal class name.
if (name == null || name.length() == 0) {
throw new IllegalArgumentException(
"Invalid " + msg + " (must not be null or empty)");
}
int max = (end == -1 ? name.length() : end);
try {
int begin = start;
int slash;
do {
slash = name.indexOf('/", begin + 1);
if (slash == -1 || slash > max) {
slash = max;
}
checkIdentifier(name, begin, slash, null);
begin = slash + 1;
} while (slash != max);
} catch (IllegalArgumentException _) {
throw new IllegalArgumentException(
"Invalid " + msg +
" (must be a fully qualified class name in internal form): " +
name);
}
| void | checkLabel(oracle.toplink.libraries.asm.Label label, boolean checkVisited, java.lang.String msg)Checks that the given label is not null. This method can also check that
the label has been visited.
if (label == null) {
throw new IllegalArgumentException(
"Invalid " + msg + " (must not be null)");
}
if (checkVisited && labels.get(label) == null) {
throw new IllegalArgumentException(
"Invalid " + msg + " (must be visited first)");
}
| static void | checkMethodDesc(java.lang.String desc)Checks that the given string is a valid method descriptor.
if (desc == null || desc.length() == 0) {
throw new IllegalArgumentException(
"Invalid method descriptor (must not be null or empty)");
}
if (desc.charAt(0) != '(" || desc.length() < 3) {
throw new IllegalArgumentException("Invalid descriptor: " + desc);
}
int start = 1;
if (desc.charAt(start) != ')") {
do {
if (desc.charAt(start) == 'V") {
throw new IllegalArgumentException("Invalid descriptor: " + desc);
}
start = checkDesc(desc, start, false);
} while (start < desc.length() && desc.charAt(start) != ')");
}
start = checkDesc(desc, start + 1, true);
if (start != desc.length()) {
throw new IllegalArgumentException("Invalid descriptor: " + desc);
}
| static void | checkMethodIdentifier(java.lang.String name, java.lang.String msg)Checks that the given string is a valid Java identifier or is equal to
'<init>' or '<clinit>'.
if (name == null || name.length() == 0) {
throw new IllegalArgumentException(
"Invalid " + msg + " (must not be null or empty)");
}
if (name.equals("<init>") || name.equals("<clinit>")) {
return;
}
if (!Character.isJavaIdentifierStart(name.charAt(0))) {
throw new IllegalArgumentException(
"Invalid " + msg +
" (must be a '<init>', '<clinit>' or a valid Java identifier): " +
name);
}
for (int i = 1; i < name.length(); ++i) {
if (!Character.isJavaIdentifierPart(name.charAt(i))) {
throw new IllegalArgumentException(
"Invalid " + msg +
" (must be '<init>' or '<clinit>' or a valid Java identifier): " +
name);
}
}
| static void | checkOpcode(int opcode, int type)Checks that the type of the given opcode is equal to the given type.
if (opcode < 0 || opcode > 199 || TYPE[opcode] != type) {
throw new IllegalArgumentException("Invalid opcode: " + opcode);
}
| static void | checkSignedByte(int value, java.lang.String msg)Checks that the given value is a signed byte.
if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) {
throw new IllegalArgumentException(
msg + " (must be a signed byte): " + value);
}
| static void | checkSignedShort(int value, java.lang.String msg)Checks that the given value is a signed short.
if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) {
throw new IllegalArgumentException(
msg + " (must be a signed short): " + value);
}
| static void | checkUnsignedShort(int value, java.lang.String msg)Checks that the given value is an unsigned short.
if (value < 0 || value > 65535) {
throw new IllegalArgumentException(
msg + " (must be an unsigned short): " + value);
}
| public void | visitAttribute(oracle.toplink.libraries.asm.Attribute attr)
if (attr == null) {
throw new IllegalArgumentException(
"Invalid attribute (must not be null)");
}
| public void | visitFieldInsn(int opcode, java.lang.String owner, java.lang.String name, java.lang.String desc)
checkEnd();
checkOpcode(opcode, 4);
checkInternalName(owner, "owner");
checkIdentifier(name, "name");
checkDesc(desc, false);
cv.visitFieldInsn(opcode, owner, name, desc);
| public void | visitIincInsn(int var, int increment)
checkEnd();
checkUnsignedShort(var, "Invalid variable index");
checkSignedShort(increment, "Invalid increment");
cv.visitIincInsn(var, increment);
| public void | visitInsn(int opcode)
checkEnd();
checkOpcode(opcode, 0);
cv.visitInsn(opcode);
| public void | visitIntInsn(int opcode, int operand)
checkEnd();
checkOpcode(opcode, 1);
switch (opcode) {
case Constants.BIPUSH:
checkSignedByte(operand, "Invalid operand");
break;
case Constants.SIPUSH:
checkSignedShort(operand, "Invalid operand");
break;
//case Constants.NEWARRAY:
default:
if (operand < Constants.T_BOOLEAN || operand > Constants.T_LONG) {
throw new IllegalArgumentException(
"Invalid operand (must be an array type code T_...): " + operand);
}
}
cv.visitIntInsn(opcode, operand);
| public void | visitJumpInsn(int opcode, oracle.toplink.libraries.asm.Label label)
checkEnd();
checkOpcode(opcode, 6);
checkLabel(label, false, "label");
cv.visitJumpInsn(opcode, label);
| public void | visitLabel(oracle.toplink.libraries.asm.Label label)
checkEnd();
checkLabel(label, false, "label");
if (labels.get(label) != null) {
throw new IllegalArgumentException("Already visited label");
} else {
labels.put(label, new Integer(labels.size()));
}
cv.visitLabel(label);
| public void | visitLdcInsn(java.lang.Object cst)
checkEnd();
if (!(cst instanceof Type)) {
checkConstant(cst);
}
cv.visitLdcInsn(cst);
| public void | visitLineNumber(int line, oracle.toplink.libraries.asm.Label start)
checkUnsignedShort(line, "Invalid line number");
checkLabel(start, true, "start label");
cv.visitLineNumber(line, start);
| public void | visitLocalVariable(java.lang.String name, java.lang.String desc, oracle.toplink.libraries.asm.Label start, oracle.toplink.libraries.asm.Label end, int index)
checkIdentifier(name, "name");
checkDesc(desc, false);
checkLabel(start, true, "start label");
checkLabel(end, true, "end label");
checkUnsignedShort(index, "Invalid variable index");
int s = ((Integer)labels.get(start)).intValue();
int e = ((Integer)labels.get(end)).intValue();
if (e <= s) {
throw new IllegalArgumentException(
"Invalid start and end labels (end must be greater than start)");
}
cv.visitLocalVariable(name, desc, start, end, index);
| public void | visitLookupSwitchInsn(oracle.toplink.libraries.asm.Label dflt, int[] keys, oracle.toplink.libraries.asm.Label[] labels)
checkEnd();
checkLabel(dflt, false, "default label");
if (keys == null || labels == null || keys.length != labels.length) {
throw new IllegalArgumentException(
"There must be the same number of keys and labels");
}
for (int i = 0; i < labels.length; ++i) {
checkLabel(labels[i], false, "label at index " + i);
}
cv.visitLookupSwitchInsn(dflt, keys, labels);
| public void | visitMaxs(int maxStack, int maxLocals)
checkEnd();
end = true;
checkUnsignedShort(maxStack, "Invalid max stack");
checkUnsignedShort(maxLocals, "Invalid max locals");
cv.visitMaxs(maxStack, maxLocals);
| public void | visitMethodInsn(int opcode, java.lang.String owner, java.lang.String name, java.lang.String desc)
checkEnd();
checkOpcode(opcode, 5);
checkInternalName(owner, "owner");
checkMethodIdentifier(name, "name");
checkMethodDesc(desc);
cv.visitMethodInsn(opcode, owner, name, desc);
| public void | visitMultiANewArrayInsn(java.lang.String desc, int dims)
checkEnd();
checkDesc(desc, false);
if (desc.charAt(0) != '[") {
throw new IllegalArgumentException(
"Invalid descriptor (must be an array type descriptor): " + desc);
}
if (dims < 1) {
throw new IllegalArgumentException(
"Invalid dimensions (must be greater than 0): " + dims);
}
if (dims > desc.lastIndexOf('[") + 1) {
throw new IllegalArgumentException(
"Invalid dimensions (must not be greater than dims(desc)): " + dims);
}
cv.visitMultiANewArrayInsn(desc, dims);
| public void | visitTableSwitchInsn(int min, int max, oracle.toplink.libraries.asm.Label dflt, oracle.toplink.libraries.asm.Label[] labels)
checkEnd();
if (max < min) {
throw new IllegalArgumentException(
"Max = " + max + " must be greater than or equal to min = " + min);
}
checkLabel(dflt, false, "default label");
if (labels == null || labels.length != max - min + 1) {
throw new IllegalArgumentException(
"There must be max - min + 1 labels");
}
for (int i = 0; i < labels.length; ++i) {
checkLabel(labels[i], false, "label at index " + i);
}
cv.visitTableSwitchInsn(min, max, dflt, labels);
| public void | visitTryCatchBlock(oracle.toplink.libraries.asm.Label start, oracle.toplink.libraries.asm.Label end, oracle.toplink.libraries.asm.Label handler, java.lang.String type)
checkLabel(start, true, "start label");
checkLabel(end, true, "end label");
checkLabel(handler, true, "handler label");
if (type != null) {
checkInternalName(type, "type");
}
int s = ((Integer)labels.get(start)).intValue();
int e = ((Integer)labels.get(end)).intValue();
if (e <= s) {
throw new IllegalArgumentException(
"Invalid start and end labels (end must be greater than start)");
}
cv.visitTryCatchBlock(start, end, handler, type);
| public void | visitTypeInsn(int opcode, java.lang.String desc)
checkEnd();
checkOpcode(opcode, 3);
if (desc != null && desc.length() > 0 && desc.charAt(0) == '[") {
checkDesc(desc, false);
} else {
checkInternalName(desc, "type");
}
if (opcode == Constants.NEW && desc.charAt(0) == '[") {
throw new IllegalArgumentException(
"NEW cannot be used to create arrays: " + desc);
}
cv.visitTypeInsn(opcode, desc);
| public void | visitVarInsn(int opcode, int var)
checkEnd();
checkOpcode(opcode, 2);
checkUnsignedShort(var, "Invalid variable index");
cv.visitVarInsn(opcode, var);
|
|