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

CheckClassAdapter

public class CheckClassAdapter extends ClassAdapter
A {@link ClassAdapter ClassAdapter} that checks that its methods are properly used. More precisely this class adapter checks each method call individually, based only on its arguments, but does not check the sequence of method calls. For example, the invalid sequence visitField(ACC_PUBLIC, "i", "I", null) visitField(ACC_PUBLIC, "i", "D", null) will not be detected by this class adapter.
author
Eric Bruneton

Fields Summary
private boolean
start
true if the visit method has been called.
private boolean
end
true if the visitEnd method has been called.
Constructors Summary
public CheckClassAdapter(ClassVisitor cv)
Constructs a new {@link CheckClassAdapter CheckClassAdapter} object.

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

    super(cv);
  
Methods Summary
static voidcheckAccess(int access, int possibleAccess)
Checks that the given access flags do not contain invalid flags. This method also checks that mutually incompatible flags are not set simultaneously.

param
access the access flags to be checked
param
possibleAccess the valid access flags.

    if ((access & ~possibleAccess) != 0) {
      throw new IllegalArgumentException("Invalid access flags: " + access);
    }
    int pub = ((access & Constants.ACC_PUBLIC) != 0 ? 1 : 0);
    int pri = ((access & Constants.ACC_PRIVATE) != 0 ? 1 : 0);
    int pro = ((access & Constants.ACC_PROTECTED) != 0 ? 1 : 0);
    if (pub + pri + pro > 1) {
      throw new IllegalArgumentException(
        "public private and protected are mutually exclusive: " + access);
    }
    int fin = ((access & Constants.ACC_FINAL) != 0 ? 1 : 0);
    int abs = ((access & Constants.ACC_ABSTRACT) != 0 ? 1 : 0);
    if (fin + abs > 1) {
      throw new IllegalArgumentException(
        "final and abstract are mutually exclusive: " + access);
    }
  
private voidcheckState()
Checks that the visit method has been called and that visitEnd has not been called.

    if (!start) {
      throw new IllegalStateException(
        "Cannot visit member before visit has been called.");
    }
    if (end) {
      throw new IllegalStateException(
        "Cannot visit member after visitEnd has been called.");
    }
  
public static voidmain(java.lang.String[] args)
Checks a given class.

Usage: CheckClassAdapter <fully qualified class name or class file name>

param
args the command line arguments.
throws
Exception if the class cannot be found, or if an IO exception occurs.

    if (args.length != 1) {
      printUsage();
    }
    ClassReader cr;
    if (args[0].endsWith(".class")) {
      cr = new ClassReader(new FileInputStream(args[0]));
    } else {
      cr = new ClassReader(args[0]);
    }
    
    TreeClassAdapter ca = new TreeClassAdapter(null);
    cr.accept(new CheckClassAdapter(ca), true);
    
    List methods = ca.classNode.methods;
    for (int i = 0; i < methods.size(); ++i) {
      MethodNode method = (MethodNode)methods.get(i);
      if (method.instructions.size() > 0) {
        Analyzer a = new Analyzer(new SimpleVerifier());
        try {
          a.analyze(ca.classNode, method);
          continue;
        } catch (Exception e) {
          e.printStackTrace();
        }
        final Frame[] frames = a.getFrames();
        
        System.out.println(method.name + method.desc);
        TraceCodeVisitor cv = new TraceCodeVisitor(null) {
          public void visitMaxs (int maxStack, int maxLocals) {
            for (int i = 0; i < text.size(); ++i) {
              String s = frames[i] == null ? "null" : frames[i].toString();
              while (s.length() < maxStack+maxLocals+1) {
                s += " ";
              }
              System.out.print(
                  Integer.toString(i + 100000).substring(1) + " " + s + " : " 
                  + text.get(i));
            }
            System.out.println();
          }
        };
        for (int j = 0; j < method.instructions.size(); ++j) {
          Object insn = method.instructions.get(j);
          if (insn instanceof AbstractInsnNode) {
            ((AbstractInsnNode)insn).accept(cv);
          } else {
            cv.visitLabel((Label)insn);
          }
        }
        cv.visitMaxs(method.maxStack, method.maxLocals);
      }
    }
  
private static voidprintUsage()

    System.err.println("TODO.");
    System.err.println("Usage: CheckClassAdapter " +
                       "<fully qualified class name or class file name>");
    System.exit(-1);
  
public voidvisit(int version, int access, java.lang.String name, java.lang.String superName, java.lang.String[] interfaces, java.lang.String sourceFile)

    if (start) {
      throw new IllegalStateException("visit must be called only once");
    } else {
      start = true;
    }
    checkState();
    checkAccess(
      access,
      Constants.ACC_PUBLIC + 
      Constants.ACC_FINAL +   
      Constants.ACC_SUPER +   
      Constants.ACC_INTERFACE +   
      Constants.ACC_ABSTRACT +   
      Constants.ACC_SYNTHETIC +   
      Constants.ACC_ANNOTATION +
      Constants.ACC_ENUM +
      Constants.ACC_DEPRECATED);
    CheckCodeAdapter.checkInternalName(name, "class name");
    if (name.equals("java/lang/Object")) {
      if (superName != null) {
        throw new IllegalArgumentException(
          "The super class name of the Object class must be 'null'");
      }
    } else {
      CheckCodeAdapter.checkInternalName(superName, "super class name");
    }
    if ((access & Constants.ACC_INTERFACE) != 0) {
      if (!superName.equals("java/lang/Object")) {
        throw new IllegalArgumentException(
          "The super class name of interfaces must be 'java/lang/Object'");
      }
    }
    if (interfaces != null) {
      for (int i = 0; i < interfaces.length; ++i) {
        CheckCodeAdapter.checkInternalName(
          interfaces[i], "interface name at index " + i);
      }
    }
    cv.visit(version, access, name, superName, interfaces, sourceFile);
  
public voidvisitAttribute(oracle.toplink.libraries.asm.Attribute attr)

    checkState();
    if (attr == null) {
      throw new IllegalArgumentException(
        "Invalid attribute (must not be null)");
    }
  
public voidvisitEnd()

    checkState();
    end = true;
    cv.visitEnd();
  
public voidvisitField(int access, java.lang.String name, java.lang.String desc, java.lang.Object value, oracle.toplink.libraries.asm.Attribute attrs)

    checkState();
    checkAccess(
      access, 
      Constants.ACC_PUBLIC +
      Constants.ACC_PRIVATE +
      Constants.ACC_PROTECTED +
      Constants.ACC_STATIC +
      Constants.ACC_FINAL +
      Constants.ACC_VOLATILE +
      Constants.ACC_TRANSIENT +
      Constants.ACC_SYNTHETIC +
      Constants.ACC_ENUM +
      Constants.ACC_DEPRECATED);
    CheckCodeAdapter.checkIdentifier(name, "field name");
    CheckCodeAdapter.checkDesc(desc, false);
    if (value != null) {
      CheckCodeAdapter.checkConstant(value);
    }
    cv.visitField(access, name, desc, value, attrs);
  
public voidvisitInnerClass(java.lang.String name, java.lang.String outerName, java.lang.String innerName, int access)

    checkState();
    CheckCodeAdapter.checkInternalName(name, "class name");
    if (outerName != null) {
      CheckCodeAdapter.checkInternalName(outerName, "outer class name");
    }
    if (innerName != null) {
      CheckCodeAdapter.checkIdentifier(innerName, "inner class name");
    }
    checkAccess(
      access, 
      Constants.ACC_PUBLIC +
      Constants.ACC_PRIVATE +
      Constants.ACC_PROTECTED +
      Constants.ACC_STATIC +
      Constants.ACC_FINAL +
      Constants.ACC_INTERFACE +
      Constants.ACC_ABSTRACT +
      Constants.ACC_SYNTHETIC +
      Constants.ACC_ANNOTATION +
      Constants.ACC_ENUM);
    cv.visitInnerClass(name, outerName, innerName, access);
  
public oracle.toplink.libraries.asm.CodeVisitorvisitMethod(int access, java.lang.String name, java.lang.String desc, java.lang.String[] exceptions, oracle.toplink.libraries.asm.Attribute attrs)

    checkState();
    checkAccess(
      access, 
      Constants.ACC_PUBLIC +
      Constants.ACC_PRIVATE +
      Constants.ACC_PROTECTED +
      Constants.ACC_STATIC +
      Constants.ACC_FINAL +
      Constants.ACC_SYNCHRONIZED +
      Constants.ACC_BRIDGE +
      Constants.ACC_VARARGS +
      Constants.ACC_NATIVE +
      Constants.ACC_ABSTRACT +
      Constants.ACC_STRICT +
      Constants.ACC_SYNTHETIC +
      Constants.ACC_DEPRECATED);
    CheckCodeAdapter.checkMethodIdentifier(name, "method name");
    CheckCodeAdapter.checkMethodDesc(desc);
    if (exceptions != null) {
      for (int i = 0; i < exceptions.length; ++i) {
        CheckCodeAdapter.checkInternalName(
          exceptions[i], "exception name at index " + i);
      }
    }
    return new CheckCodeAdapter(
      cv.visitMethod(access, name, desc, exceptions, attrs));