1 30 31 package oracle.toplink.libraries.asm.util; 32 33 import java.io.FileInputStream ; 34 import java.util.List ; 35 36 import oracle.toplink.libraries.asm.ClassAdapter; 37 import oracle.toplink.libraries.asm.ClassReader; 38 import oracle.toplink.libraries.asm.ClassVisitor; 39 import oracle.toplink.libraries.asm.CodeVisitor; 40 import oracle.toplink.libraries.asm.Constants; 41 import oracle.toplink.libraries.asm.Attribute; 42 import oracle.toplink.libraries.asm.Label; 43 import oracle.toplink.libraries.asm.tree.AbstractInsnNode; 44 import oracle.toplink.libraries.asm.tree.MethodNode; 45 import oracle.toplink.libraries.asm.tree.TreeClassAdapter; 46 import oracle.toplink.libraries.asm.tree.analysis.Analyzer; 47 import oracle.toplink.libraries.asm.tree.analysis.SimpleVerifier; 48 import oracle.toplink.libraries.asm.tree.analysis.Frame; 49 50 60 61 public class CheckClassAdapter extends ClassAdapter { 62 63 66 67 private boolean start; 68 69 72 73 private boolean end; 74 75 86 87 public static void main (final String [] args) throws Exception { 88 if (args.length != 1) { 89 printUsage(); 90 } 91 ClassReader cr; 92 if (args[0].endsWith(".class")) { 93 cr = new ClassReader(new FileInputStream (args[0])); 94 } else { 95 cr = new ClassReader(args[0]); 96 } 97 98 TreeClassAdapter ca = new TreeClassAdapter(null); 99 cr.accept(new CheckClassAdapter(ca), true); 100 101 List methods = ca.classNode.methods; 102 for (int i = 0; i < methods.size(); ++i) { 103 MethodNode method = (MethodNode)methods.get(i); 104 if (method.instructions.size() > 0) { 105 Analyzer a = new Analyzer(new SimpleVerifier()); 106 try { 107 a.analyze(ca.classNode, method); 108 continue; 109 } catch (Exception e) { 110 e.printStackTrace(); 111 } 112 final Frame[] frames = a.getFrames(); 113 114 System.out.println(method.name + method.desc); 115 TraceCodeVisitor cv = new TraceCodeVisitor(null) { 116 public void visitMaxs (int maxStack, int maxLocals) { 117 for (int i = 0; i < text.size(); ++i) { 118 String s = frames[i] == null ? "null" : frames[i].toString(); 119 while (s.length() < maxStack+maxLocals+1) { 120 s += " "; 121 } 122 System.out.print( 123 Integer.toString(i + 100000).substring(1) + " " + s + " : " 124 + text.get(i)); 125 } 126 System.out.println(); 127 } 128 }; 129 for (int j = 0; j < method.instructions.size(); ++j) { 130 Object insn = method.instructions.get(j); 131 if (insn instanceof AbstractInsnNode) { 132 ((AbstractInsnNode)insn).accept(cv); 133 } else { 134 cv.visitLabel((Label)insn); 135 } 136 } 137 cv.visitMaxs(method.maxStack, method.maxLocals); 138 } 139 } 140 } 141 142 private static void printUsage () { 143 System.err.println("TODO."); 144 System.err.println("Usage: CheckClassAdapter " + 145 "<fully qualified class name or class file name>"); 146 System.exit(-1); 147 } 148 149 154 155 public CheckClassAdapter (final ClassVisitor cv) { 156 super(cv); 157 } 158 159 public void visit ( 160 final int version, 161 final int access, 162 final String name, 163 final String superName, 164 final String [] interfaces, 165 final String sourceFile) 166 { 167 if (start) { 168 throw new IllegalStateException ("visit must be called only once"); 169 } else { 170 start = true; 171 } 172 checkState(); 173 checkAccess( 174 access, 175 Constants.ACC_PUBLIC + 176 Constants.ACC_FINAL + 177 Constants.ACC_SUPER + 178 Constants.ACC_INTERFACE + 179 Constants.ACC_ABSTRACT + 180 Constants.ACC_SYNTHETIC + 181 Constants.ACC_ANNOTATION + 182 Constants.ACC_ENUM + 183 Constants.ACC_DEPRECATED); 184 CheckCodeAdapter.checkInternalName(name, "class name"); 185 if (name.equals("java/lang/Object")) { 186 if (superName != null) { 187 throw new IllegalArgumentException ( 188 "The super class name of the Object class must be 'null'"); 189 } 190 } else { 191 CheckCodeAdapter.checkInternalName(superName, "super class name"); 192 } 193 if ((access & Constants.ACC_INTERFACE) != 0) { 194 if (!superName.equals("java/lang/Object")) { 195 throw new IllegalArgumentException ( 196 "The super class name of interfaces must be 'java/lang/Object'"); 197 } 198 } 199 if (interfaces != null) { 200 for (int i = 0; i < interfaces.length; ++i) { 201 CheckCodeAdapter.checkInternalName( 202 interfaces[i], "interface name at index " + i); 203 } 204 } 205 cv.visit(version, access, name, superName, interfaces, sourceFile); 206 } 207 208 public void visitInnerClass ( 209 final String name, 210 final String outerName, 211 final String innerName, 212 final int access) 213 { 214 checkState(); 215 CheckCodeAdapter.checkInternalName(name, "class name"); 216 if (outerName != null) { 217 CheckCodeAdapter.checkInternalName(outerName, "outer class name"); 218 } 219 if (innerName != null) { 220 CheckCodeAdapter.checkIdentifier(innerName, "inner class name"); 221 } 222 checkAccess( 223 access, 224 Constants.ACC_PUBLIC + 225 Constants.ACC_PRIVATE + 226 Constants.ACC_PROTECTED + 227 Constants.ACC_STATIC + 228 Constants.ACC_FINAL + 229 Constants.ACC_INTERFACE + 230 Constants.ACC_ABSTRACT + 231 Constants.ACC_SYNTHETIC + 232 Constants.ACC_ANNOTATION + 233 Constants.ACC_ENUM); 234 cv.visitInnerClass(name, outerName, innerName, access); 235 } 236 237 public void visitField ( 238 final int access, 239 final String name, 240 final String desc, 241 final Object value, 242 final Attribute attrs) 243 { 244 checkState(); 245 checkAccess( 246 access, 247 Constants.ACC_PUBLIC + 248 Constants.ACC_PRIVATE + 249 Constants.ACC_PROTECTED + 250 Constants.ACC_STATIC + 251 Constants.ACC_FINAL + 252 Constants.ACC_VOLATILE + 253 Constants.ACC_TRANSIENT + 254 Constants.ACC_SYNTHETIC + 255 Constants.ACC_ENUM + 256 Constants.ACC_DEPRECATED); 257 CheckCodeAdapter.checkIdentifier(name, "field name"); 258 CheckCodeAdapter.checkDesc(desc, false); 259 if (value != null) { 260 CheckCodeAdapter.checkConstant(value); 261 } 262 cv.visitField(access, name, desc, value, attrs); 263 } 264 265 public CodeVisitor visitMethod ( 266 final int access, 267 final String name, 268 final String desc, 269 final String [] exceptions, 270 final Attribute attrs) 271 { 272 checkState(); 273 checkAccess( 274 access, 275 Constants.ACC_PUBLIC + 276 Constants.ACC_PRIVATE + 277 Constants.ACC_PROTECTED + 278 Constants.ACC_STATIC + 279 Constants.ACC_FINAL + 280 Constants.ACC_SYNCHRONIZED + 281 Constants.ACC_BRIDGE + 282 Constants.ACC_VARARGS + 283 Constants.ACC_NATIVE + 284 Constants.ACC_ABSTRACT + 285 Constants.ACC_STRICT + 286 Constants.ACC_SYNTHETIC + 287 Constants.ACC_DEPRECATED); 288 CheckCodeAdapter.checkMethodIdentifier(name, "method name"); 289 CheckCodeAdapter.checkMethodDesc(desc); 290 if (exceptions != null) { 291 for (int i = 0; i < exceptions.length; ++i) { 292 CheckCodeAdapter.checkInternalName( 293 exceptions[i], "exception name at index " + i); 294 } 295 } 296 return new CheckCodeAdapter( 297 cv.visitMethod(access, name, desc, exceptions, attrs)); 298 } 299 300 public void visitAttribute (final Attribute attr) { 301 checkState(); 302 if (attr == null) { 303 throw new IllegalArgumentException ( 304 "Invalid attribute (must not be null)"); 305 } 306 } 307 308 public void visitEnd () { 309 checkState(); 310 end = true; 311 cv.visitEnd(); 312 } 313 314 316 320 321 private void checkState () { 322 if (!start) { 323 throw new IllegalStateException ( 324 "Cannot visit member before visit has been called."); 325 } 326 if (end) { 327 throw new IllegalStateException ( 328 "Cannot visit member after visitEnd has been called."); 329 } 330 } 331 332 340 341 static void checkAccess (final int access, final int possibleAccess) { 342 if ((access & ~possibleAccess) != 0) { 343 throw new IllegalArgumentException ("Invalid access flags: " + access); 344 } 345 int pub = ((access & Constants.ACC_PUBLIC) != 0 ? 1 : 0); 346 int pri = ((access & Constants.ACC_PRIVATE) != 0 ? 1 : 0); 347 int pro = ((access & Constants.ACC_PROTECTED) != 0 ? 1 : 0); 348 if (pub + pri + pro > 1) { 349 throw new IllegalArgumentException ( 350 "public private and protected are mutually exclusive: " + access); 351 } 352 int fin = ((access & Constants.ACC_FINAL) != 0 ? 1 : 0); 353 int abs = ((access & Constants.ACC_ABSTRACT) != 0 ? 1 : 0); 354 if (fin + abs > 1) { 355 throw new IllegalArgumentException ( 356 "final and abstract are mutually exclusive: " + access); 357 } 358 } 359 } 360 | Popular Tags |