1 22 package org.jboss.reflect.plugins.javassist; 23 24 import java.security.AccessController ; 25 import java.security.PrivilegedActionException ; 26 import java.security.PrivilegedExceptionAction ; 27 28 import javassist.ClassPool; 29 import javassist.CtClass; 30 import javassist.CtConstructor; 31 import javassist.CtField; 32 import javassist.CtMethod; 33 import javassist.CtNewMethod; 34 import javassist.Modifier; 35 import javassist.NotFoundException; 36 37 import org.jboss.util.JBossStringBuilder; 38 import org.jboss.util.UnreachableStatementException; 39 40 import EDU.oswego.cs.dl.util.concurrent.SynchronizedInt; 41 42 50 public class JavassistReflectionFactory 51 { 52 53 private static final SynchronizedInt counter = new SynchronizedInt(0); 54 55 56 private final boolean check; 57 58 63 public JavassistReflectionFactory(boolean check) 64 { 65 this.check = check; 66 } 67 68 75 public JavassistMethod createMethod(CtMethod ctMethod) throws Throwable 76 { 77 ClassPool pool = JavassistTypeInfoFactoryImpl.pool; 78 final CtClass result = pool.makeClass(JavassistMethod.class.getName() + counter.increment()); 79 try 80 { 81 CtClass magic = pool.get("sun.reflect.MagicAccessorImpl"); 82 result.setSuperclass(magic); 83 } 84 catch (NotFoundException ignored) 85 { 86 } 87 result.addInterface(pool.get(JavassistMethod.class.getName())); 88 89 CtConstructor constructor = new CtConstructor(null, result); 90 constructor.setBody("super();"); 91 result.addConstructor(constructor); 92 93 CtClass object = pool.get(Object .class.getName()); 94 95 JBossStringBuilder buffer = new JBossStringBuilder(); 96 97 buffer.append("public Object invoke(Object target, Object[] args) throws Throwable {"); 99 100 boolean isInstanceMethod = Modifier.isStatic(ctMethod.getModifiers()) == false; 101 102 if (check && isInstanceMethod) 104 { 105 buffer.append("if (target == null) throw new IllegalArgumentException(\"Null target for "); 106 buffer.append(ctMethod.getName()).append(ctMethod.getSignature()).append("\");"); 107 } 108 109 CtClass declaring = ctMethod.getDeclaringClass(); 111 boolean needsCast = isInstanceMethod && object.equals(declaring) == false; 112 if (check && needsCast) 113 { 114 buffer.append("if (target instanceof ").append(declaring.getName()).append(" == false) "); 115 buffer.append("throw new IllegalArgumentException(\"Target \" + target + \""); 116 buffer.append(" is not an instance of ").append(declaring.getName()); 117 buffer.append(" for ").append(ctMethod.getName()).append(ctMethod.getSignature()).append("\");"); 118 } 119 120 CtClass[] params = ctMethod.getParameterTypes(); 122 if (check) 123 { 124 if (params.length != 0) 126 { 127 buffer.append("if (args == null || args.length != ").append(params.length).append(") "); 128 buffer.append("throw new IllegalArgumentException(\"Expected ").append(params.length).append(" parameter(s)"); 129 buffer.append(" for ").append(ctMethod.getName()).append(ctMethod.getSignature()).append("\");"); 130 } 131 else 132 { 133 buffer.append("if (args != null && args.length != 0)"); 135 buffer.append("throw new IllegalArgumentException(\"Expected no parameters"); 136 buffer.append(" for ").append(ctMethod.getName()).append(ctMethod.getSignature()).append("\");"); 137 } 138 for (int i = 0; i < params.length; ++i) 139 { 140 if (object.equals(params[i]) == false) 141 { 142 String paramType = getBoxedType(params[i]); 143 if (params[i].isPrimitive()) 145 { 146 buffer.append("if (args[").append(i).append("] == null) "); 147 buffer.append("throw new IllegalArgumentException(\"Parameter ").append(i); 148 buffer.append(" cannot be null for ").append(params[i].getName()); 149 buffer.append(" for ").append(ctMethod.getName()).append(ctMethod.getSignature()).append("\");"); 150 } 151 buffer.append("if (args[").append(i).append("] != null && "); 153 buffer.append("args[").append(i).append("] instanceof ").append(paramType).append(" == false) "); 154 buffer.append("throw new IllegalArgumentException(\"Parameter ").append(i).append(" \" + args[").append(i).append("] + \""); 155 buffer.append(" is not an instance of ").append(paramType); 156 buffer.append(" for ").append(ctMethod.getName()).append(ctMethod.getSignature()).append("\");"); 157 } 158 } 159 } 160 161 CtClass returnType = ctMethod.getReturnType(); 163 boolean isVoid = CtClass.voidType.equals(returnType); 164 boolean isPrimitive = returnType.isPrimitive(); 165 if (isVoid == false) 166 { 167 buffer.append("return "); 168 if (isPrimitive) 169 buffer.append("new ").append(getBoxedType(returnType)).append('('); 170 } 171 172 if (isInstanceMethod) 174 { 175 buffer.append('('); 176 if (needsCast) 177 buffer.append("(").append(declaring.getName()).append(')'); 178 179 buffer.append("target)."); 180 } 181 else 182 { 183 buffer.append(declaring.getName()).append('.'); 185 } 186 187 buffer.append(ctMethod.getName()).append('('); 189 190 for (int i = 0; i < params.length; ++i) 192 { 193 buffer.append('('); 194 if (object.equals(params[i]) == false) 196 buffer.append("(").append(getBoxedType(params[i])).append(')'); 197 buffer.append("args[").append(i).append("])"); 198 if (params[i].isPrimitive()) 200 unbox(buffer, params[i]); 201 202 if (i < params.length - 1) 203 buffer.append(", "); 204 } 205 buffer.append(')'); 206 207 if (isVoid == false && isPrimitive) 209 buffer.append(')'); 210 211 buffer.append(';'); 212 213 if (isVoid) 215 buffer.append("return null;"); 216 buffer.append('}'); 217 218 String code = buffer.toString(); 220 try 221 { 222 CtMethod invoke = CtNewMethod.make(code, result); 223 result.addMethod(invoke); 224 } 225 catch (Exception e) 226 { 227 throw new RuntimeException ("Cannot compile " + code, e); 228 } 229 230 try 232 { 233 return AccessController.doPrivileged(new PrivilegedExceptionAction <JavassistMethod>() 234 { 235 public JavassistMethod run() throws Exception 236 { 237 Class clazz = result.toClass(); 238 return (JavassistMethod) clazz.newInstance(); 239 } 240 }); 241 } 242 catch (PrivilegedActionException e) 243 { 244 throw e.getCause(); 245 } 246 } 247 248 255 public JavassistConstructor createConstructor(CtConstructor ctConstructor) throws Throwable 256 { 257 ClassPool pool = JavassistTypeInfoFactoryImpl.pool; 258 final CtClass result = pool.makeClass(JavassistConstructor.class.getName() + counter.increment()); 259 try 260 { 261 CtClass magic = pool.get("sun.reflect.MagicAccessorImpl"); 262 result.setSuperclass(magic); 263 } 264 catch (NotFoundException ignored) 265 { 266 } 267 result.addInterface(pool.get(JavassistConstructor.class.getName())); 268 269 CtConstructor constructor = new CtConstructor(null, result); 270 constructor.setBody("super();"); 271 result.addConstructor(constructor); 272 273 CtClass object = pool.get(Object .class.getName()); 274 275 JBossStringBuilder buffer = new JBossStringBuilder(); 276 277 buffer.append("public Object newInstance(Object[] args) throws Throwable {"); 279 280 String declaring = ctConstructor.getDeclaringClass().getName(); 281 282 CtClass[] params = ctConstructor.getParameterTypes(); 284 if (check) 285 { 286 if (params.length != 0) 288 { 289 buffer.append("if (args == null || args.length != ").append(params.length).append(") "); 290 buffer.append("throw new IllegalArgumentException(\"Expected ").append(params.length).append(" parameter(s)"); 291 buffer.append(" for ").append("new ").append(declaring).append(ctConstructor.getSignature()).append("\");"); 292 } 293 else 294 { 295 buffer.append("if (args != null && args.length != 0)"); 297 buffer.append("throw new IllegalArgumentException(\"Expected no parameters"); 298 buffer.append(" for ").append("new ").append(declaring).append(ctConstructor.getSignature()).append("\");"); 299 } 300 for (int i = 0; i < params.length; ++i) 301 { 302 if (object.equals(params[i]) == false) 303 { 304 String paramType = getBoxedType(params[i]); 305 if (params[i].isPrimitive()) 307 { 308 buffer.append("if (args[").append(i).append("] == null) "); 309 buffer.append("throw new IllegalArgumentException(\"Parameter ").append(i); 310 buffer.append(" cannot be null for ").append(params[i].getName()); 311 buffer.append(" for ").append("new ").append(declaring).append(ctConstructor.getSignature()).append("\");"); 312 } 313 buffer.append("if (args[").append(i).append("] != null && "); 315 buffer.append("args[").append(i).append("] instanceof ").append(paramType).append(" == false) "); 316 buffer.append("throw new IllegalArgumentException(\"Parameter ").append(i).append(" \" + args[").append(i).append("] + \""); 317 buffer.append(" is not an instance of ").append(paramType); 318 buffer.append(" for ").append("new ").append(declaring).append(ctConstructor.getSignature()).append("\");"); 319 } 320 } 321 } 322 323 buffer.append("return new ").append(declaring).append('('); 325 326 for (int i = 0; i < params.length; ++i) 328 { 329 buffer.append('('); 330 if (object.equals(params[i]) == false) 332 buffer.append("(").append(getBoxedType(params[i])).append(')'); 333 buffer.append("args[").append(i).append("])"); 334 if (params[i].isPrimitive()) 336 unbox(buffer, params[i]); 337 338 if (i < params.length - 1) 339 buffer.append(", "); 340 } 341 buffer.append(");}"); 342 343 String code = buffer.toString(); 345 try 346 { 347 CtMethod newInstance = CtNewMethod.make(code, result); 348 result.addMethod(newInstance); 349 } 350 catch (Exception e) 351 { 352 throw new RuntimeException ("Cannot compile " + code, e); 353 } 354 355 try 357 { 358 return AccessController.doPrivileged(new PrivilegedExceptionAction <JavassistConstructor>() 359 { 360 public JavassistConstructor run() throws Exception 361 { 362 Class clazz = result.toClass(); 363 return (JavassistConstructor) clazz.newInstance(); 364 } 365 }); 366 } 367 catch (PrivilegedActionException e) 368 { 369 throw e.getCause(); 370 } 371 } 372 373 380 public JavassistField createField(CtField ctField) throws Throwable 381 { 382 ClassPool pool = JavassistTypeInfoFactoryImpl.pool; 383 final CtClass result = pool.makeClass(JavassistField.class.getName() + counter.increment()); 384 try 385 { 386 CtClass magic = pool.get("sun.reflect.MagicAccessorImpl"); 387 result.setSuperclass(magic); 388 } 389 catch (NotFoundException ignored) 390 { 391 } 392 result.addInterface(pool.get(JavassistField.class.getName())); 393 394 CtConstructor constructor = new CtConstructor(null, result); 395 constructor.setBody("super();"); 396 result.addConstructor(constructor); 397 398 CtClass object = pool.get(Object .class.getName()); 399 400 JBossStringBuilder buffer = new JBossStringBuilder(); 402 403 buffer.append("public Object get(Object target) throws Throwable {"); 405 406 boolean isInstanceField= Modifier.isStatic(ctField.getModifiers()) == false; 407 408 if (check && isInstanceField) 410 { 411 buffer.append("if (target == null) throw new IllegalArgumentException(\"Null target"); 412 buffer.append(" for ").append(ctField.getName()).append("\");"); 413 } 414 415 CtClass declaring = ctField.getDeclaringClass(); 417 boolean needsCast = isInstanceField && object.equals(declaring) == false; 418 if (check && needsCast) 419 { 420 buffer.append("if (target instanceof ").append(declaring.getName()).append(" == false) "); 421 buffer.append("throw new IllegalArgumentException(\"Target \" + target + \""); 422 buffer.append(" is not an instance of ").append(declaring.getName()); 423 buffer.append(" for ").append(ctField.getName()).append("\");"); 424 } 425 426 CtClass type = ctField.getType(); 428 boolean isPrimitive = type.isPrimitive(); 429 buffer.append("return "); 430 if (isPrimitive) 431 buffer.append("new ").append(getBoxedType(type)).append('('); 432 433 if (isInstanceField) 435 { 436 buffer.append('('); 437 if (needsCast) 438 buffer.append("(").append(declaring.getName()).append(')'); 439 440 buffer.append("target)."); 441 } 442 else 443 { 444 buffer.append(declaring.getName()).append('.'); 446 } 447 448 buffer.append(ctField.getName()); 450 451 if (isPrimitive) 453 buffer.append(')'); 454 455 buffer.append(";}"); 456 457 String code = buffer.toString(); 459 CtMethod get = CtNewMethod.make(code, result); 460 try 461 { 462 result.addMethod(get); 463 } 464 catch (Exception e) 465 { 466 throw new RuntimeException ("Cannot compile " + code, e); 467 } 468 469 buffer = new JBossStringBuilder(); 471 472 buffer.append("public void set(Object target, Object value) throws Throwable {"); 474 475 if (check && isInstanceField) 477 { 478 buffer.append("if (target == null) throw new IllegalArgumentException(\"Null target"); 479 buffer.append(" for ").append(ctField.getName()).append("\");"); 480 } 481 482 if (check && needsCast) 484 { 485 buffer.append("if (target instanceof ").append(declaring.getName()).append(" == false) "); 486 buffer.append("throw new IllegalArgumentException(\"Target \" + target + \""); 487 buffer.append(" is not an instance of ").append(declaring.getName()); 488 buffer.append(" for ").append(ctField.getName()).append("\");"); 489 } 490 491 if (check) 493 { 494 if (object.equals(type) == false) 495 { 496 String paramType = getBoxedType(type); 497 if (type.isPrimitive()) 499 { 500 buffer.append("if (type == null) "); 501 buffer.append("throw new IllegalArgumentException(\"Value "); 502 buffer.append(" cannot be null for ").append(type.getName()); 503 buffer.append(" for ").append(ctField.getName()).append("\");"); 504 } 505 buffer.append("if (value != null && "); 507 buffer.append("value instanceof ").append(paramType).append(" == false) "); 508 buffer.append("throw new IllegalArgumentException(\"Value \" + value + \""); 509 buffer.append(" is not an instance of ").append(paramType); 510 buffer.append(" for ").append(ctField.getName()).append("\");"); 511 } 512 } 513 514 if (isInstanceField) 516 { 517 buffer.append('('); 518 if (needsCast) 519 buffer.append("(").append(declaring.getName()).append(')'); 520 521 buffer.append("target)."); 522 } 523 else 524 { 525 buffer.append(declaring.getName()).append('.'); 527 } 528 529 buffer.append(ctField.getName()).append("="); 531 532 buffer.append('('); 534 if (object.equals(type) == false) 536 buffer.append("(").append(getBoxedType(type)).append(')'); 537 buffer.append("value)"); 538 if (type.isPrimitive()) 540 unbox(buffer, type); 541 542 buffer.append(";}"); 543 544 code = buffer.toString(); 546 try 547 { 548 CtMethod set = CtNewMethod.make(code, result); 549 result.addMethod(set); 550 } 551 catch (Exception e) 552 { 553 throw new RuntimeException ("Cannot compile " + code, e); 554 } 555 556 try 558 { 559 return AccessController.doPrivileged(new PrivilegedExceptionAction <JavassistField>() 560 { 561 public JavassistField run() throws Exception 562 { 563 Class clazz = result.toClass(); 564 return (JavassistField) clazz.newInstance(); 565 } 566 }); 567 } 568 catch (PrivilegedActionException e) 569 { 570 throw e.getCause(); 571 } 572 } 573 574 580 protected void unbox(JBossStringBuilder buffer, CtClass primitive) 581 { 582 if (CtClass.booleanType.equals(primitive)) 583 buffer.append(".booleanValue()"); 584 else if (CtClass.byteType.equals(primitive)) 585 buffer.append(".byteValue()"); 586 else if (CtClass.charType.equals(primitive)) 587 buffer.append(".charValue()"); 588 else if (CtClass.doubleType.equals(primitive)) 589 buffer.append(".doubleValue()"); 590 else if (CtClass.floatType.equals(primitive)) 591 buffer.append(".floatValue()"); 592 else if (CtClass.intType.equals(primitive)) 593 buffer.append(".intValue()"); 594 else if (CtClass.longType.equals(primitive)) 595 buffer.append(".longValue()"); 596 else if (CtClass.shortType.equals(primitive)) 597 buffer.append(".shortValue()"); 598 else 599 { 600 throw new UnreachableStatementException(); 601 } 602 } 603 604 611 protected String getBoxedType(CtClass type) 612 { 613 if (type.isPrimitive()) 614 { 615 if (CtClass.booleanType.equals(type)) 616 return Boolean .class.getName(); 617 else if (CtClass.byteType.equals(type)) 618 return Byte .class.getName(); 619 else if (CtClass.charType.equals(type)) 620 return Character .class.getName(); 621 else if (CtClass.doubleType.equals(type)) 622 return Double .class.getName(); 623 else if (CtClass.floatType.equals(type)) 624 return Float .class.getName(); 625 else if (CtClass.intType.equals(type)) 626 return Integer .class.getName(); 627 else if (CtClass.longType.equals(type)) 628 return Long .class.getName(); 629 else if (CtClass.shortType.equals(type)) 630 return Short .class.getName(); 631 throw new UnreachableStatementException(); 632 } 633 return type.getName(); 634 } 635 } 636 | Popular Tags |