FileDocCategorySizeDatePackage
CheckCodeAdapter.javaAPI DocGlassfish v2 API24035Thu Mar 02 11:51:18 GMT 2006oracle.toplink.libraries.asm.util

CheckCodeAdapter

public 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.
author
Eric Bruneton

Fields Summary
private boolean
end
true if the visitMaxs method has been called.
private HashMap
labels
The already visited labels. This map associate Integer values to Label keys.
private static final int[]
TYPE
Code of the visit method to be used for each opcode.
Constructors Summary
public CheckCodeAdapter(CodeVisitor cv)
Constructs a new {@link CheckCodeAdapter CheckCodeAdapter} object.

param
cv the code visitor to which this adapter must delegate calls.


                        

       
    super(cv);
    this.labels = new HashMap();
  
Methods Summary
static voidcheckConstant(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}.

param
cst the value to be checked.

    if (!(cst instanceof Integer) &&
      !(cst instanceof Float) &&
      !(cst instanceof Long) &&
      !(cst instanceof Double) &&
      !(cst instanceof String))
    {
      throw new IllegalArgumentException("Invalid constant: " + cst);
    }
  
static voidcheckDesc(java.lang.String desc, boolean canBeVoid)
Checks that the given string is a valid type descriptor.

param
desc the string to be checked.
param
canBeVoid true if V can be considered valid.

    int end = checkDesc(desc, 0, canBeVoid);
    if (end != desc.length()) {
      throw new IllegalArgumentException("Invalid descriptor: " + desc);
    }
  
static intcheckDesc(java.lang.String desc, int start, boolean canBeVoid)
Checks that a the given substring is a valid type descriptor.

param
desc the string to be checked.
param
start index of the first character of the identifier (inclusive).
param
canBeVoid true if V can be considered valid.
return
the index of the last character of the type decriptor, plus one.

    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);
    }
  
voidcheckEnd()
Checks that the visitMaxs method has not been called.

    if (end) {
      throw new IllegalStateException(
        "Cannot visit instructions after visitMaxs has been called.");
    }
  
static voidcheckIdentifier(java.lang.String name, java.lang.String msg)
Checks that the given string is a valid Java identifier.

param
name the string to be checked.
param
msg a message to be used in case of error.

    checkIdentifier(name, 0, -1, msg);
  
static voidcheckIdentifier(java.lang.String name, int start, int end, java.lang.String msg)
Checks that the given substring is a valid Java identifier.

param
name the string to be checked.
param
start index of the first character of the identifier (inclusive).
param
end index of the last character of the identifier (exclusive). -1 is equivalent to name.length() if name is not null.
param
msg a message to be used in case of error.

    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 voidcheckInternalName(java.lang.String name, java.lang.String msg)
Checks that the given string is a valid internal class name.

param
name the string to be checked.
param
msg a message to be used in case of error.

    checkInternalName(name, 0, -1, msg);
  
static voidcheckInternalName(java.lang.String name, int start, int end, java.lang.String msg)
Checks that the given substring is a valid internal class name.

param
name the string to be checked.
param
start index of the first character of the identifier (inclusive).
param
end index of the last character of the identifier (exclusive). -1 is equivalent to name.length() if name is not null.
param
msg a message to be used in case of error.

    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);
    }
  
voidcheckLabel(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.

param
label the label to be checked.
param
checkVisited true to check that the label has been visited.
param
msg a message to be used in case of error.

    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 voidcheckMethodDesc(java.lang.String desc)
Checks that the given string is a valid method descriptor.

param
desc the string to be checked.

    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 voidcheckMethodIdentifier(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>'.

param
name the string to be checked.
param
msg a message to be used in case of error.

    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 voidcheckOpcode(int opcode, int type)
Checks that the type of the given opcode is equal to the given type.

param
opcode the opcode to be checked.
param
type the expected opcode type.

    if (opcode < 0 || opcode > 199 || TYPE[opcode] != type) {
      throw new IllegalArgumentException("Invalid opcode: " + opcode);
    }
  
static voidcheckSignedByte(int value, java.lang.String msg)
Checks that the given value is a signed byte.

param
value the value to be checked.
param
msg an message to be used in case of error.

    if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) {
      throw new IllegalArgumentException(
        msg + " (must be a signed byte): " + value);
    }
  
static voidcheckSignedShort(int value, java.lang.String msg)
Checks that the given value is a signed short.

param
value the value to be checked.
param
msg an message to be used in case of error.

    if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) {
      throw new IllegalArgumentException(
        msg + " (must be a signed short): " + value);
    }
  
static voidcheckUnsignedShort(int value, java.lang.String msg)
Checks that the given value is an unsigned short.

param
value the value to be checked.
param
msg an message to be used in case of error.

    if (value < 0 || value > 65535) {
      throw new IllegalArgumentException(
        msg + " (must be an unsigned short): " + value);
    }
  
public voidvisitAttribute(oracle.toplink.libraries.asm.Attribute attr)

    if (attr == null) {
      throw new IllegalArgumentException(
        "Invalid attribute (must not be null)");
    }
  
public voidvisitFieldInsn(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 voidvisitIincInsn(int var, int increment)

    checkEnd();
    checkUnsignedShort(var, "Invalid variable index");
    checkSignedShort(increment, "Invalid increment");
    cv.visitIincInsn(var, increment);
  
public voidvisitInsn(int opcode)

    checkEnd();
    checkOpcode(opcode, 0);
    cv.visitInsn(opcode);
  
public voidvisitIntInsn(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 voidvisitJumpInsn(int opcode, oracle.toplink.libraries.asm.Label label)

    checkEnd();
    checkOpcode(opcode, 6);
    checkLabel(label, false, "label");
    cv.visitJumpInsn(opcode, label);
  
public voidvisitLabel(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 voidvisitLdcInsn(java.lang.Object cst)

    checkEnd();
    if (!(cst instanceof Type)) {
      checkConstant(cst);
    }
    cv.visitLdcInsn(cst);
  
public voidvisitLineNumber(int line, oracle.toplink.libraries.asm.Label start)

    checkUnsignedShort(line, "Invalid line number");
    checkLabel(start, true, "start label");
    cv.visitLineNumber(line, start);
  
public voidvisitLocalVariable(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 voidvisitLookupSwitchInsn(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 voidvisitMaxs(int maxStack, int maxLocals)

    checkEnd();
    end = true;
    checkUnsignedShort(maxStack, "Invalid max stack");
    checkUnsignedShort(maxLocals, "Invalid max locals");
    cv.visitMaxs(maxStack, maxLocals);
  
public voidvisitMethodInsn(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 voidvisitMultiANewArrayInsn(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 voidvisitTableSwitchInsn(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 voidvisitTryCatchBlock(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 voidvisitTypeInsn(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 voidvisitVarInsn(int opcode, int var)

    checkEnd();
    checkOpcode(opcode, 2);
    checkUnsignedShort(var, "Invalid variable index");
    cv.visitVarInsn(opcode, var);