1 15 16 package javassist.compiler; 17 18 import java.util.List ; 19 import javassist.*; 20 import javassist.bytecode.*; 21 import javassist.compiler.ast.*; 22 23 25 public class MemberResolver implements TokenId { 26 private ClassPool classPool; 27 28 public MemberResolver(ClassPool cp) { 29 classPool = cp; 30 } 31 32 public ClassPool getClassPool() { return classPool; } 33 34 private static void fatal() throws CompileError { 35 throw new CompileError("fatal"); 36 } 37 38 41 public void recordPackage(String jvmClassName) { 42 String classname = jvmToJavaName(jvmClassName); 43 for (;;) { 44 int i = classname.lastIndexOf('.'); 45 if (i > 0) { 46 classname = classname.substring(0, i); 47 classPool.recordInvalidClassName(classname); 48 } 49 else 50 break; 51 } 52 } 53 54 public static class Method { 55 public CtClass declaring; 56 public MethodInfo info; 57 58 public Method(CtClass c, MethodInfo i) { 59 declaring = c; 60 info = i; 61 } 62 63 66 public boolean isStatic() { 67 int acc = info.getAccessFlags(); 68 return (acc & AccessFlag.STATIC) != 0; 69 } 70 } 71 72 public Method lookupMethod(CtClass clazz, MethodInfo current, 73 String methodName, 74 int[] argTypes, int[] argDims, 75 String [] argClassNames, boolean onlyExact) 76 throws CompileError 77 { 78 Method maybe = null; 79 80 if (current != null) 82 if (current.getName().equals(methodName)) { 83 int res = compareSignature(current.getDescriptor(), 84 argTypes, argDims, argClassNames); 85 Method r = new Method(clazz, current); 86 if (res == YES) 87 return r; 88 else if (res == MAYBE && maybe == null) 89 maybe = r; 90 } 91 92 List list = clazz.getClassFile2().getMethods(); 93 int n = list.size(); 94 for (int i = 0; i < n; ++i) { 95 MethodInfo minfo = (MethodInfo)list.get(i); 96 if (minfo.getName().equals(methodName)) { 97 int res = compareSignature(minfo.getDescriptor(), 98 argTypes, argDims, argClassNames); 99 Method r = new Method(clazz, minfo); 100 if (res == YES) 101 return r; 102 else if (res == MAYBE && maybe == null) 103 maybe = r; 104 } 105 } 106 107 try { 108 CtClass pclazz = clazz.getSuperclass(); 109 if (pclazz != null) { 110 Method r = lookupMethod(pclazz, null, methodName, argTypes, 111 argDims, argClassNames, 112 (onlyExact || maybe != null)); 113 if (r != null) 114 return r; 115 } 116 } 117 catch (NotFoundException e) {} 118 119 int mod = clazz.getModifiers(); 120 if (Modifier.isAbstract(mod) || Modifier.isInterface(mod)) 121 try { 122 CtClass[] ifs = clazz.getInterfaces(); 123 int size = ifs.length; 124 for (int i = 0; i < size; ++i) { 125 Method r = lookupMethod(ifs[i], null, methodName, 126 argTypes, argDims, argClassNames, 127 (onlyExact || maybe != null)); 128 if (r != null) 129 return r; 130 } 131 } 132 catch (NotFoundException e) {} 133 134 if (onlyExact) 135 return null; 136 else 137 return maybe; 138 } 139 140 private static final int YES = 2; 141 private static final int MAYBE = 1; 142 private static final int NO = 0; 143 144 152 private int compareSignature(String desc, int[] argTypes, 153 int[] argDims, String [] argClassNames) 154 throws CompileError 155 { 156 int result = YES; 157 int i = 1; 158 int nArgs = argTypes.length; 159 if (nArgs != Descriptor.numOfParameters(desc)) 160 return NO; 161 162 int len = desc.length(); 163 for (int n = 0; i < len; ++n) { 164 char c = desc.charAt(i++); 165 if (c == ')') 166 return (n == nArgs ? result : NO); 167 else if (n >= nArgs) 168 return NO; 169 170 int dim = 0; 171 while (c == '[') { 172 ++dim; 173 c = desc.charAt(i++); 174 } 175 176 if (argTypes[n] == NULL) { 177 if (dim == 0 && c != 'L') 178 return NO; 179 180 if (c == 'L') 181 i = desc.indexOf(';', i) + 1; 182 } 183 else if (argDims[n] != dim) { 184 if (!(dim == 0 && c == 'L' 185 && desc.startsWith("java/lang/Object;", i))) 186 return NO; 187 188 i = desc.indexOf(';', i) + 1; 190 result = MAYBE; 191 if (i <= 0) 192 return NO; } 194 else if (c == 'L') { int j = desc.indexOf(';', i); 196 if (j < 0 || argTypes[n] != CLASS) 197 return NO; 198 199 String cname = desc.substring(i, j); 200 if (!cname.equals(argClassNames[n])) { 201 CtClass clazz = lookupClassByJvmName(argClassNames[n]); 202 try { 203 if (clazz.subtypeOf(lookupClassByJvmName(cname))) 204 result = MAYBE; 205 else 206 return NO; 207 } 208 catch (NotFoundException e) { 209 result = MAYBE; } 211 } 212 213 i = j + 1; 214 } 215 else { 216 int t = descToType(c); 217 int at = argTypes[n]; 218 if (t != at) 219 if (t == INT 220 && (at == SHORT || at == BYTE || at == CHAR)) 221 result = MAYBE; 222 else 223 return NO; 224 } 225 } 226 227 return NO; 228 } 229 230 235 public CtField lookupFieldByJvmName2(String jvmClassName, Symbol fieldSym, 236 ASTree expr) throws NoFieldException 237 { 238 String field = fieldSym.get(); 239 CtClass cc = null; 240 try { 241 cc = lookupClass(jvmToJavaName(jvmClassName), true); 242 } 243 catch (CompileError e) { 244 throw new NoFieldException(jvmClassName + "/" + field, expr); 246 } 247 248 try { 249 return cc.getField(field); 250 } 251 catch (NotFoundException e) { 252 jvmClassName = javaToJvmName(cc.getName()); 254 throw new NoFieldException(jvmClassName + "$" + field, expr); 255 } 256 } 257 258 261 public CtField lookupFieldByJvmName(String jvmClassName, Symbol fieldName) 262 throws CompileError 263 { 264 return lookupField(jvmToJavaName(jvmClassName), fieldName); 265 } 266 267 270 public CtField lookupField(String className, Symbol fieldName) 271 throws CompileError 272 { 273 CtClass cc = lookupClass(className, false); 274 try { 275 return cc.getField(fieldName.get()); 276 } 277 catch (NotFoundException e) {} 278 throw new CompileError("no such field: " + fieldName.get()); 279 } 280 281 public CtClass lookupClassByName(ASTList name) throws CompileError { 282 return lookupClass(Declarator.astToClassName(name, '.'), false); 283 } 284 285 public CtClass lookupClassByJvmName(String jvmName) throws CompileError { 286 return lookupClass(jvmToJavaName(jvmName), false); 287 } 288 289 public CtClass lookupClass(Declarator decl) throws CompileError { 290 return lookupClass(decl.getType(), decl.getArrayDim(), 291 decl.getClassName()); 292 } 293 294 297 public CtClass lookupClass(int type, int dim, String classname) 298 throws CompileError 299 { 300 String cname = ""; 301 CtClass clazz; 302 switch (type) { 303 case CLASS : 304 clazz = lookupClassByJvmName(classname); 305 if (dim > 0) 306 cname = clazz.getName(); 307 else 308 return clazz; 309 310 break; 311 case BOOLEAN : 312 cname = "boolean"; 313 break; 314 case CHAR : 315 cname = "char"; 316 break; 317 case BYTE : 318 cname = "byte"; 319 break; 320 case SHORT : 321 cname = "short"; 322 break; 323 case INT : 324 cname = "int"; 325 break; 326 case LONG : 327 cname = "long"; 328 break; 329 case FLOAT : 330 cname = "float"; 331 break; 332 case DOUBLE : 333 cname = "double"; 334 break; 335 case VOID : 336 cname = "void"; 337 break; 338 default : 339 fatal(); 340 } 341 342 while (dim-- > 0) 343 cname += "[]"; 344 345 return lookupClass(cname, false); 346 } 347 348 351 public CtClass lookupClass(String name, boolean notCheckInner) 352 throws CompileError 353 { 354 try { 355 return lookupClass0(name, notCheckInner); 356 } 357 catch (NotFoundException e) {} 358 if (name.indexOf('.') < 0) { 359 String jlangName = "java.lang." + name; 360 try { 361 CtClass cc = classPool.get(jlangName); 362 classPool.recordInvalidClassName(name); 364 return cc; 365 } 366 catch (NotFoundException e) { 367 classPool.recordInvalidClassName(jlangName); 368 } 369 } 370 371 throw new CompileError("no such class: " + name); 372 } 373 374 private CtClass lookupClass0(String classname, boolean notCheckInner) 375 throws NotFoundException 376 { 377 CtClass cc = null; 378 do { 379 try { 380 cc = classPool.get(classname); 381 } 382 catch (NotFoundException e) { 383 int i = classname.lastIndexOf('.'); 384 if (notCheckInner || i < 0) 385 throw e; 386 else { 387 StringBuffer sbuf = new StringBuffer (classname); 388 sbuf.setCharAt(i, '$'); 389 classname = sbuf.toString(); 390 } 391 } 392 } while (cc == null); 393 return cc; 394 } 395 396 401 public String resolveClassName(ASTList name) throws CompileError { 402 if (name == null) 403 return null; 404 else 405 return javaToJvmName(lookupClassByName(name).getName()); 406 } 407 408 411 public String resolveJvmClassName(String jvmName) throws CompileError { 412 if (jvmName == null) 413 return null; 414 else 415 return javaToJvmName(lookupClassByJvmName(jvmName).getName()); 416 } 417 418 public static CtClass getSuperclass(CtClass c) throws CompileError { 419 try { 420 return c.getSuperclass(); 421 } 422 catch (NotFoundException e) { 423 throw new CompileError("cannot find the super class of " 424 + c.getName()); 425 } 426 } 427 428 public static String javaToJvmName(String classname) { 429 return classname.replace('.', '/'); 430 } 431 432 public static String jvmToJavaName(String classname) { 433 return classname.replace('/', '.'); 434 } 435 436 public static int descToType(char c) throws CompileError { 437 switch (c) { 438 case 'Z' : 439 return BOOLEAN; 440 case 'C' : 441 return CHAR; 442 case 'B' : 443 return BYTE; 444 case 'S' : 445 return SHORT; 446 case 'I' : 447 return INT; 448 case 'J' : 449 return LONG; 450 case 'F' : 451 return FLOAT; 452 case 'D' : 453 return DOUBLE; 454 case 'V' : 455 return VOID; 456 case 'L' : 457 case '[' : 458 return CLASS; 459 default : 460 fatal(); 461 return VOID; } 463 } 464 465 public static int getModifiers(ASTList mods) { 466 int m = 0; 467 while (mods != null) { 468 Keyword k = (Keyword)mods.head(); 469 mods = mods.tail(); 470 switch (k.get()) { 471 case STATIC : 472 m |= Modifier.STATIC; 473 break; 474 case FINAL : 475 m |= Modifier.FINAL; 476 break; 477 case SYNCHRONIZED : 478 m |= Modifier.SYNCHRONIZED; 479 break; 480 case ABSTRACT : 481 m |= Modifier.ABSTRACT; 482 break; 483 case PUBLIC : 484 m |= Modifier.PUBLIC; 485 break; 486 case PROTECTED : 487 m |= Modifier.PROTECTED; 488 break; 489 case PRIVATE : 490 m |= Modifier.PRIVATE; 491 break; 492 case VOLATILE : 493 m |= Modifier.VOLATILE; 494 break; 495 case TRANSIENT : 496 m |= Modifier.TRANSIENT; 497 break; 498 case STRICT : 499 m |= Modifier.STRICT; 500 break; 501 } 502 } 503 504 return m; 505 } 506 } 507 | Popular Tags |