1 22 package org.jboss.proxy.compiler; 23 24 import java.lang.reflect.Method ; 25 import java.lang.reflect.Constructor ; 26 import java.lang.reflect.InvocationTargetException ; 27 import java.lang.reflect.Modifier ; 28 import java.lang.reflect.Member ; 29 30 import java.io.Serializable ; 31 32 import java.util.ArrayList ; 33 import java.util.Hashtable ; 34 35 43 public final class Proxies 44 { 45 48 private Proxies() 49 { 50 super(); 51 } 52 53 87 public static ProxyTarget newTarget(ClassLoader parent, 88 InvocationHandler invocationHandler, 89 Class targetTypes[]) 90 throws Exception 91 { 92 return Impl.getImpl(targetTypes).newTarget(invocationHandler, parent); 93 } 94 95 99 public interface ProxyTarget 100 extends Serializable 101 { 102 106 InvocationHandler getInvocationHandler(); 107 108 111 Class [] getTargetTypes(); 112 } 113 114 135 public static ProxyInvocationHandler newInvocationHandler(Object target, 136 Class targetType) 137 { 138 return Impl.getImpl(targetType).newInvocationHandler(target); 139 } 140 141 public static ProxyInvocationHandler newInvocationHandler(Object target, 142 Class targetTypes[]) 143 { 144 return Impl.getImpl(targetTypes).newInvocationHandler(target); 145 } 146 147 151 public interface ProxyInvocationHandler 152 extends InvocationHandler, Serializable 153 { 154 158 Object getTarget(); 159 } 160 161 171 public static Object getTarget(InvocationHandler invocationHandler) 172 { 173 if (invocationHandler instanceof ProxyInvocationHandler) 174 { 175 Object target = ((ProxyInvocationHandler)invocationHandler).getTarget(); 176 if (target != null) 177 { 178 return target; 179 } 180 } 182 183 return null; 184 } 185 186 198 public static InvocationHandler getInvocationHandler(Object target, 199 Class targetTypes[]) 200 { 201 if (target instanceof ProxyTarget) 202 { 203 ProxyTarget tproxy = (ProxyTarget)target; 204 InvocationHandler invocationHandler = tproxy.getInvocationHandler(); 205 if (targetTypes == null || 206 Impl.sameTypes(tproxy.getTargetTypes(), targetTypes)) 207 { 208 return invocationHandler; 209 } 210 } 212 return newInvocationHandler(target, targetTypes); 213 } 214 215 public static InvocationHandler getInvocationHandler(Object target, 216 Class targetType) 217 { 218 if (targetType == null) 220 { 221 return getInvocationHandler(target, (Class [])null); 222 } 223 224 return getInvocationHandler(target, new Class [] { targetType }); 225 } 226 227 239 public static Method [] getMethods(Class targetType) 240 { 241 return Impl.getImpl(targetType).copyMethods(); 242 } 243 244 public static Method [] getMethods(Class targetTypes[]) 245 { 246 return Impl.getImpl(targetTypes).copyMethods(); 247 } 248 249 public static void forgetProxyForClass(Class clazz) 250 { 251 Impl.forgetProxyForClass(clazz); 252 } 253 254 257 static class Impl 258 implements Serializable 259 { 260 static Hashtable impls = new Hashtable (); 261 262 263 Class targetTypes[]; 264 265 Method methods[]; 266 267 268 Impl more; 269 270 Class superclass = Object .class; 271 272 273 String proxyString; 274 275 Constructor proxyConstructor; 276 277 Impl(Class targetTypes[]) 278 { 279 this.targetTypes = targetTypes; 280 281 Method methodLists[][] = new Method [targetTypes.length][]; 282 for (int i = 0; i < targetTypes.length; i++) 283 { 284 methodLists[i] = checkTargetType(targetTypes[i]); 285 } 286 287 checkSuperclass(); 288 this.methods = combineMethodLists(methodLists); 289 } 290 291 static synchronized Impl getImpl(Class targetType) 292 { 293 Impl impl = (Impl) impls.get(targetType); 294 if (impl == null) 295 { 296 impl = new Impl(new Class [] { targetType }); 297 impls.put(targetType, impl); 298 } 299 return impl; 300 } 301 302 static synchronized Impl getImpl(Class targetTypes[]) 303 { 304 int n = targetTypes.length; 305 if (n == 1) 306 { 307 return getImpl(targetTypes[0]); 308 } 309 for (int i = 0; i < n; ++i) 312 { 313 for (Impl impl = (Impl) impls.get(targetTypes[i]); impl != null; impl = impl.more) 314 { 315 if (sameTypes(targetTypes, impl.targetTypes)) 316 return impl; 317 } 318 } 319 320 targetTypes = copyAndUniquify(targetTypes); 322 Impl impl1 = getImpl(new Class [] { targetTypes[0] }); 323 Impl impl = new Impl(targetTypes); 324 impl.more = impl1.more; 325 impl1.more = impl; 326 return impl; 327 } 328 329 341 static synchronized void forgetProxyForClass(Class clazz) 342 { 343 impls.remove(clazz); 344 } 345 346 347 static boolean sameTypes(Class tt1[], Class tt2[]) 350 { 351 if (tt1.length == 1 && tt2.length == 1) 352 { 353 return tt1[0] == tt2[0]; 354 } 355 356 int totalSeen2 = 0; 357 each_type: 358 for (int i = tt1.length; --i >= 0; ) 359 { 360 Class c = tt1[i]; 361 for (int j = i; --j >= 0; ) 362 { 363 if (c == tt1[j]) 364 { 365 continue each_type; 366 } 367 } 368 int seen2 = 0; 371 for (int j = tt2.length; --j >= 0; ) 372 { 373 if (c == tt2[j]) 374 { 375 ++seen2; 376 } 377 } 378 379 if (seen2 == 0) 380 { 381 return false; 383 } 384 totalSeen2 += seen2; 385 } 386 return totalSeen2 == tt2.length; 388 } 389 390 static Class [] copyAndUniquify(Class targetTypes[]) 391 { 392 int n = targetTypes.length; 393 Class tt[] = new Class [n]; 394 int k = 0; 395 each_type: 396 for (int i = 0; i < n; i++) 397 { 398 Class c = targetTypes[i]; 399 for (int j = i; --j >= 0; ) 400 { 401 if (c == targetTypes[j]) 402 { 403 continue each_type; 404 } 405 } 406 tt[k++] = c; 407 } 408 if (k < n) 409 { 410 Class tt0[] = new Class [k]; 412 for (int i = 0; i < k; i++) 413 { 414 tt0[i] = tt[i]; 415 } 416 tt = tt0; 417 } 418 return tt; 419 } 420 421 Method [] checkTargetType(Class targetType) 424 { 425 if (targetType.isArray()) 426 { 427 throw new IllegalArgumentException 428 ("cannot subclass an array type: " + targetType.getName()); 429 } 430 431 if (targetType.isPrimitive()) 432 { 433 throw new IllegalArgumentException 434 ("cannot subclass a primitive type: " + targetType); 435 } 436 437 int tmod = targetType.getModifiers(); 438 if (Modifier.isFinal(tmod)) 439 { 440 throw new IllegalArgumentException 441 ("cannot subclass a final type: " + targetType); 442 } 443 444 if (!Modifier.isPublic(tmod)) 445 { 446 throw new IllegalArgumentException 447 ("cannot subclass a non-public type: " + targetType); 448 } 449 450 if (!targetType.isInterface()) 452 { 453 if (!targetType.isAssignableFrom(superclass)) 454 { 455 if (superclass.isAssignableFrom(targetType)) 456 { 457 superclass = targetType; 458 } 459 else { 460 throw new IllegalArgumentException 461 ("inconsistent superclass: " + targetType); 462 } 463 } 464 } 465 466 Method methodList[] = targetType.getMethods(); 468 int nm = 0; 469 for (int i = 0; i < methodList.length; i++) 470 { 471 Method m = methodList[i]; 472 if (eligibleForInvocationHandler(m)) 473 { 474 methodList[nm++] = m; } 476 } 477 478 while (nm < methodList.length) 479 { 480 methodList[nm++] = null; } 482 483 return methodList; 484 } 485 486 void checkSuperclass() 487 { 488 Constructor constructors[] = superclass.getConstructors(); 489 for (int i = 0; i < constructors.length; i++) 490 { 491 Constructor c = constructors[i]; 492 int mod = c.getModifiers(); 493 if (Modifier.isPublic(mod) 494 && c.getParameterTypes().length == 0) 495 { 496 return; } 498 } 499 500 throw new IllegalArgumentException 501 ("cannot subclass without nullary constructor: " 502 +superclass.getName()); 503 } 504 505 509 static boolean eligibleForInvocationHandler(Method m) 510 { 511 int mod = m.getModifiers(); 512 513 if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) 514 { 515 return false; 517 } 518 519 if (!Modifier.isAbstract(mod)) 520 { 521 return false; 523 } 524 525 return true; 526 } 527 528 534 static boolean areEqual(Method m1, Method m2) 535 { 536 if( ! m1.getName().equals(m2.getName()) ) 538 return false; 539 540 Class a1[] = m1.getParameterTypes(); 542 Class a2[] = m2.getParameterTypes(); 543 if( a1.length != a2.length ) 544 return false; 545 for( int i=0; i < a1.length; i++) 546 if( !a1[i].equals(a2[i]) ) 547 return false; 548 549 return true; 550 } 551 552 556 static Method [] combineMethodLists(Method methodLists[][]) 557 { 558 int nm = 0; 559 for (int i = 0; i < methodLists.length; i++) 560 { 561 nm += methodLists[i].length; 562 } 563 Method methods[] = new Method [nm]; 564 565 nm=0; 567 for (int i = 0; i < methodLists.length; i++) 568 for (int j = 0; j < methodLists[i].length; j++) 569 methods[nm++]=methodLists[i][j]; 570 571 for( int i=0; i < methods.length; i++ ) 573 { 574 if( methods[i] == null ) 575 continue; 576 for( int j=i+1; j < methods.length; j++ ) 577 { 578 if( methods[j] == null ) 579 continue; 580 if( areEqual(methods[i], methods[j]) ) 581 { 582 methods[j]=null; 583 nm--; 584 } 585 } 586 } 587 588 ArrayList tmp = new ArrayList (); 590 for (int i = 0; i < methods.length; i++) 591 { 592 if( methods[i] != null ) 593 tmp.add(methods[i]); 594 } 595 Method methodsCopy[] = new Method [tmp.size()]; 596 tmp.toArray(methodsCopy); 597 return methodsCopy; 598 } 599 600 Method [] copyMethods() 601 { 602 return (Method [])methods.clone(); 603 } 604 605 Class [] copyTargetTypes() 606 { 607 return (Class [])targetTypes.clone(); 608 } 609 610 ProxyTarget newTarget(InvocationHandler invocationHandler, 611 ClassLoader parent) 612 throws Exception 613 { 614 if (proxyConstructor == null) 615 { 616 ProxyCompiler pc = new ProxyCompiler(parent, 618 superclass, 619 targetTypes, 620 methods); 621 622 Class type[] = { InvocationHandler.class }; 623 proxyConstructor = pc.getProxyType().getConstructor(type); 624 } 625 626 Object args[] = { invocationHandler }; 627 return (ProxyTarget)proxyConstructor.newInstance(args); 628 } 629 630 ProxyInvocationHandler newInvocationHandler(final Object target) 631 { 632 if (proxyString == null) 633 { 634 String s = "InvocationHandler@" + targetTypes[0].getName(); 635 for (int i = 1; i < targetTypes.length; i++) 636 { 637 s += "," + targetTypes[i].getName(); 638 } 639 proxyString = s; 640 } 641 642 return new ProxyInvocationHandler() 643 { 644 public Object getTarget() 646 { 647 return target; 648 } 649 650 public Class [] getTargetTypes() 651 { 652 return copyTargetTypes(); 653 } 654 655 public String toString() 656 { 657 return proxyString + "[" + target + "]"; 658 } 659 660 public Object invoke(Object dummy, 661 Method method, 662 Object values[]) 663 throws Throwable 664 { 665 return Impl.this.invoke(target, method, values); 666 } 667 }; 668 } 669 670 673 Object invoke(Object target, Member method, Object values[]) 674 throws Throwable 675 { 676 682 try 683 { 684 Method methods[] = this.methods; 686 for (int i = methods.length; --i >= 0; ) 688 { 689 if (methods[i] == method) 690 { 691 return methods[i].invoke(target, values); 692 } 693 } 694 695 if (method == null) 697 { 698 if (methods.length == 1) 699 { 700 return methods[0].invoke(target, values); 701 } 702 throw new IllegalArgumentException ("non-unique method"); 703 } 704 705 for (int i = methods.length; --i >= 0; ) 707 { 708 if (methods[i].equals(method)) 709 { 710 return methods[i].invoke(target, values); 711 } 712 } 713 714 } 715 catch (InvocationTargetException e) 716 { 717 throw e.getTargetException(); 718 } 719 720 throw new IllegalArgumentException ("method unexpected "+method); 721 } 722 } 723 } 724 | Popular Tags |