| 1 18 19 package org.objectweb.jac.core; 20 21 import java.lang.reflect.InvocationTargetException ; 22 import java.lang.reflect.Method ; 23 import java.util.Arrays ; 24 import java.util.Collection ; 25 import java.util.HashMap ; 26 import java.util.Hashtable ; 27 import java.util.Iterator ; 28 import java.util.List ; 29 import java.util.Map ; 30 import java.util.Vector ; 31 import org.aopalliance.intercept.ConstructorInterceptor; 32 import org.aopalliance.intercept.Interceptor; 33 import org.aopalliance.intercept.MethodInterceptor; 34 import org.apache.log4j.Logger; 35 import org.objectweb.jac.core.rtti.AbstractMethodItem; 36 import org.objectweb.jac.core.rtti.ClassItem; 37 import org.objectweb.jac.core.rtti.ClassRepository; 38 import org.objectweb.jac.core.rtti.ConstructorItem; 39 import org.objectweb.jac.core.rtti.MethodItem; 40 import org.objectweb.jac.core.rtti.MixinMethodItem; 41 import org.objectweb.jac.core.rtti.NamingConventions; 42 import org.objectweb.jac.util.Strings; 43 import org.objectweb.jac.util.WrappedThrowableException; 44 45 51 52 public class Wrapping { 53 static Logger logger = Logger.getLogger("wrapping"); 54 static Logger loggerExc = Logger.getLogger("exceptions"); 55 static Logger loggerRole = Logger.getLogger("rolemethod"); 56 static Logger loggerWuni = Logger.getLogger("wuni"); 57 58 60 62 static transient Map wrappingChains = new java.util.WeakHashMap (); 63 65 static transient Map staticWrappingChains = new Hashtable (); 66 67 68 static transient Map catchingChains = new java.util.WeakHashMap (); 69 70 71 static transient Map staticCatchingChains = new Hashtable (); 72 73 74 static transient Map wrappers = new java.util.WeakHashMap (); 75 76 77 static transient Map staticWrappers = new Hashtable (); 78 79 80 static transient Map wrapperClasses = new java.util.WeakHashMap (); 81 82 83 static transient Map staticWrapperClasses = new Hashtable (); 84 85 public static final Object [] emptyArray = new Object [0]; 86 87 95 public static WrappingChain getWrappingChain( 96 Wrappee wrappee, 97 AbstractMethodItem method) 98 { 99 101 if (method.isStatic()) { 102 WrappingChain result = 103 (WrappingChain) staticWrappingChains.get(method); 104 if (result == null) { 105 result = new WrappingChain(); 106 staticWrappingChains.put(method, result); 107 } 108 return result; 110 } else { 111 Map wrappeeChains = (Map ) wrappingChains.get(wrappee); 112 if (wrappeeChains == null) { 113 wrappeeChains = new Hashtable (); 114 wrappingChains.put(wrappee, wrappeeChains); 115 } 116 WrappingChain result = (WrappingChain) wrappeeChains.get(method); 117 if (result == null) { 118 result = new WrappingChain(); 119 wrappeeChains.put(method, result); 120 } 121 return result; 122 } 123 } 124 125 133 public static List getCatchingChain( 134 Wrappee wrappee, 135 AbstractMethodItem method) 136 { 137 if (method.isStatic()) { 138 List chain = (List ) staticCatchingChains.get(method); 139 if (chain == null) { 140 chain = new Vector (); 141 staticCatchingChains.put(method, chain); 142 } 143 return chain; 144 } else { 145 Map wrappeeChain = (Map ) catchingChains.get(wrappee); 146 if (wrappeeChain == null) { 147 wrappeeChain = new Hashtable (); 148 catchingChains.put(wrappee, wrappeeChain); 149 } 150 List chain = (List ) wrappeeChain.get(method); 151 if (chain == null) { 152 chain = new Vector (); 153 wrappeeChain.put(method, chain); 154 } 155 return chain; 156 } 157 } 158 159 168 public static List getWrappers(Wrappee wrappee, ClassItem wrappeeClass) { 169 if (wrappee == null) { 170 List wrappers = (List ) staticWrappers.get(wrappeeClass); 171 if (wrappers == null) { 172 wrappers = new Vector (); 173 staticWrappers.put(wrappeeClass, wrappers); 174 } 175 return wrappers; 176 } else { 177 List result = (List ) wrappers.get(wrappee); 178 if (result == null) { 179 result = new Vector (); 180 wrappers.put(wrappee, result); 181 } 182 return result; 183 } 184 } 185 186 195 public static List getWrapperClasses( 196 Wrappee wrappee, 197 ClassItem wrappeeClass) 198 { 199 if (wrappee == null) { 200 List result = (List ) staticWrapperClasses.get(wrappeeClass); 201 if (result == null) { 202 result = new Vector (); 203 staticWrapperClasses.put(wrappeeClass, result); 204 } 205 return result; 206 } else { 207 List result = (List ) wrapperClasses.get(wrappee); 208 if (result == null) { 209 result = new Vector (); 210 wrapperClasses.put(wrappee, result); 211 } 212 return result; 213 } 214 } 215 216 231 232 public static void wrap( 233 Wrappee wrappee, 234 ClassItem wrappeeClass, 235 Wrapper wrapper) 236 { 237 logger.debug("wrapping " + wrappee + "(" + wrappeeClass + ") with " + wrapper); 238 List wrappers = getWrappers(wrappee, wrappeeClass); 239 if (wrappers.contains(wrapper)) { 240 logger.debug(" ignoring already present wrapper"); 241 return; 242 } 243 244 wrappers.add(wrapper); 245 getWrapperClasses(wrappee, wrappeeClass).add(wrapper.getClass()); 246 247 258 } 259 260 static private HashMap wrappableMethods = new HashMap (); 261 262 266 267 public static boolean isWrappable(AbstractMethodItem method) { 268 Boolean ret = (Boolean ) wrappableMethods.get(method); 270 if (ret == null) { 271 try { 272 ((ClassItem) method.getParent()).getActualClass().getField( 274 "__JAC_TRANSLATED"); 275 } catch (Exception e) { 276 wrappableMethods.put(method, Boolean.FALSE); 278 return false; 279 } 280 wrappableMethods.put(method, new Boolean (true)); 282 return true; 283 } else { 284 return ret.booleanValue(); 286 } 287 } 288 289 public static String printWrappingChain(Interceptor[] wrappingChain) { 290 String result = "["; 291 for (int i = 0; i < wrappingChain.length; i++) { 292 if (i != 0) { 293 result += ","; 294 } 295 result += wrappingChain[i].toString(); 296 } 297 298 result += "]"; 299 return result; 300 } 301 302 static CompositionAspect ca = null; 303 304 311 public static void wrap( 312 Wrappee wrappee, 313 Wrapper wrapper, 314 AbstractMethodItem wrappedMethod) 315 { 316 if (wrapMethod(wrappee,wrapper,wrappedMethod)) { 317 Wrapping.wrap(wrappee, wrappedMethod.getClassItem(), wrapper); 319 } 320 } 321 322 332 public static boolean wrapMethod( 333 Wrappee wrappee, 334 Wrapper wrapper, 335 AbstractMethodItem wrappedMethod) 336 { 337 if (isWrappable(wrappedMethod)) { 338 logger.debug(wrappedMethod + Strings.hash(wrappedMethod)+" is wrapped by " + wrapper); 339 340 WrappingChain wrappingChain = 341 getWrappingChain(wrappee, wrappedMethod.getConcreteMethod()); 342 logger.debug(" "+wrappedMethod.getConcreteMethod()+" -> "+wrappingChain+ 343 Strings.hash(wrappingChain)); 344 345 if (wrappingChain.contains(wrapper)) { 346 logger.debug(" skipping "+wrapper); 347 return false; 348 } 349 350 int rank = 0; 351 352 ACManager acm = ACManager.getACM(); 353 if (acm != null) { 354 if (ca == null) 355 ca = (CompositionAspect) acm.objects.get( 356 "JAC_composition_aspect"); 357 if (ca != null) { 358 rank = ca.getWeaveTimeRank(wrappingChain, wrapper); 359 } else { 361 368 } 369 } 370 371 wrappingChain.add(rank, wrapper); 372 return true; 373 } else { 375 return false; 377 } 378 379 } 380 381 391 public static void wrap( 392 Wrappee wrappee, 393 Wrapper wrapper, 394 AbstractMethodItem[] wrappedMethods) 395 { 396 if (wrappedMethods == null) 397 return; 398 for (int i = 0; i < wrappedMethods.length; i++) { 399 if (wrappedMethods[i] != null) { 400 wrap(wrappee, wrapper, wrappedMethods[i]); 401 } 402 } 403 } 404 405 416 public static void wrap( 417 Wrappee wrappee, 418 Wrapper wrapper, 419 String [] wrappedMethods) 420 { 421 ClassItem cli = ClassRepository.get().getClass(wrappee); 422 if (wrappedMethods == null) 423 return; 424 for (int i = 0; i < wrappedMethods.length; i++) { 425 if (wrappedMethods[i] != null) { 426 try { 427 MethodItem[] methods = cli.getMethods(wrappedMethods[i]); 428 for (int j = 0; j < methods.length; j++) { 429 wrap(wrappee, wrapper, methods[j]); 430 } 431 } catch (org.objectweb.jac.core.rtti.NoSuchMethodException e) { 432 logger.error("wrap "+wrappee+","+wrapper+","+Arrays.asList(wrappedMethods)+": "+e); 433 } 434 } 435 } 436 } 437 438 447 public static void wrapAll( 448 Wrappee wrappee, 449 ClassItem wrappeeClass, 450 Wrapper wrapper) 451 { 452 Collection methods = null; 453 if (wrappeeClass != null) { 454 methods = wrappeeClass.getAllMethods(); 455 } else { 456 methods = 457 ClassRepository 458 .get() 459 .getClass(wrappee.getClass()) 460 .getAllMethods(); 461 } 462 Iterator i = methods.iterator(); 463 while (i.hasNext()) { 464 wrap(wrappee, wrapper, (AbstractMethodItem) i.next()); 465 } 466 } 467 468 476 public static void wrapModifiers(Wrappee wrappee, Wrapper wrapper) { 477 try { 478 Collection methods = 479 ClassRepository.get().getClass(wrappee).getAllModifiers(); 480 Iterator i = methods.iterator(); 481 while (i.hasNext()) { 482 MethodItem method = (MethodItem) i.next(); 483 wrap(wrappee, wrapper, method); 484 } 485 } catch (Exception e) { 486 e.printStackTrace(); 487 } 488 } 489 490 508 public static void unwrap( 509 Wrappee wrappee, 510 ClassItem wrappeeClass, 511 Wrapper wrapper) 512 { 513 List wrappers = getWrappers(wrappee, wrappeeClass); 514 if (!wrappers.contains(wrapper)) 515 return; 516 logger.debug("unwrapping " + wrappee + " with " + wrapper); 517 wrappers.remove(wrapper); 518 getWrapperClasses(wrappee, wrappeeClass).remove(wrapper.getClass()); 519 unwrapAll(wrappee, wrappeeClass, wrapper); 520 } 521 522 529 public static void unwrap( 530 Wrappee wrappee, 531 ClassItem wrappeeClass, 532 Collection acWrappers) 533 { 534 List wrappers = getWrappers(wrappee, wrappeeClass); 535 Iterator it = wrappers.iterator(); 537 while(it.hasNext()) { 538 Wrapper wrapper = (Wrapper)it.next(); 539 if (acWrappers.contains(wrapper)) { 540 logger.debug("unwrapping " + wrappee + " with " + wrapper); 541 it.remove(); 542 getWrapperClasses(wrappee, wrappeeClass).remove(wrapper.getClass()); 543 unwrapAll(wrappee, wrappeeClass, wrapper); 544 } else { 545 logger.debug("leaving "+wrapper); 546 } 547 } 548 } 549 550 568 public static void unwrap( 569 Wrappee wrappee, 570 Wrapper wrapper, 571 AbstractMethodItem wrappedMethod) 572 { 573 logger.debug("unwrapping " + (wrappee != null ? wrappee.getClass().getName() : "-")+ 574 "."+wrappedMethod+"("+Strings.hex(wrappedMethod)+"-"+ 575 Strings.hex(wrappedMethod.getClassItem())+")"+ 576 " with "+wrapper+"???"); 577 WrappingChain wrappingChain = getWrappingChain(wrappee, wrappedMethod.getConcreteMethod()); 578 for (int i=0; i<wrappingChain.size(); i++) { 579 if (wrappingChain.get(i) == wrapper) { 580 logger.debug("unwrapping "+wrappedMethod+"("+Strings.hex(wrappedMethod)+")"+ 581 " with "+wrapper); 582 wrappingChain.remove(i); 583 } 584 } 585 } 586 587 public static void unwrapAll( 588 Wrappee wrappee, 589 ClassItem wrappeeClass, 590 Wrapper wrapper) 591 { 592 logger.debug("unwrapAll "+wrappeeClass+"-"+Strings.hex(wrappeeClass)+ 593 "-"+wrappeeClass.getClass().getClassLoader()); 594 Collection methods = wrappeeClass.getAllMethods(); 595 Iterator i = methods.iterator(); 596 while (i.hasNext()) { 597 AbstractMethodItem m = (AbstractMethodItem)i.next(); 598 if (!(m instanceof MixinMethodItem)) 599 unwrap(wrappee, wrapper, m); 600 } 601 } 602 603 606 public static boolean isWrappedBy( 607 Wrappee wrappee, 608 ClassItem wrappeeClass, 609 Wrapper wrapper) 610 { 611 return getWrappers(wrappee, wrappeeClass).contains(wrapper); 612 } 613 614 618 public static boolean isWrappedBy( 619 Wrappee wrappee, 620 ClassItem wrappeeClass, 621 Class wrapperClass) 622 { 623 return getWrapperClasses(wrappee, wrappeeClass).contains(wrapperClass); 624 } 625 626 630 public static boolean isExtendedBy( 631 Wrappee wrappee, 632 ClassItem wrappeeClass, 633 Class wrapperClass) 634 { 635 Iterator i = getWrapperClasses(wrappee, wrappeeClass).iterator(); 636 while (i.hasNext()) { 637 Class cl = (Class ) i.next(); 638 if (wrapperClass.isAssignableFrom(cl)) 639 return true; 640 } 641 return false; 642 } 643 644 public static void addExceptionHandler( 645 Wrappee wrappee, 646 Wrapper wrapper, 647 String method, 648 AbstractMethodItem listenedMethod) 649 { 650 Vector catchingChain = 651 (Vector ) getCatchingChain(wrappee, listenedMethod); 652 653 Object [] catchingMethod = new Object [2]; 654 catchingMethod[0] = wrapper; 655 Method [] methods = 656 ClassRepository.getDirectMethodAccess(wrapper.getClass(), method); 657 if (methods.length > 0) { 658 catchingMethod[1] = methods[0]; 659 catchingChain.add(catchingMethod); 660 } else { 661 throw new NoSuchMethodError ( 662 "No such method " 663 + method 664 + " in class " 665 + wrapper.getClass().getName()); 666 } 667 } 668 669 public static void addExceptionHandler( 670 Wrappee wrappee, 671 Wrapper wrapper, 672 String method) 673 { 674 Collection meths = 675 ClassRepository.get().getClass(wrappee.getClass()).getAllMethods(); 676 Iterator i = meths.iterator(); 677 while (i.hasNext()) { 678 addExceptionHandler( 679 wrappee, 680 wrapper, 681 method, 682 (AbstractMethodItem) i.next()); 683 } 684 } 685 686 700 public static Object invokeRoleMethod( 701 Wrappee wrappee, 702 String methodName, 703 Object [] parameters) 704 { 705 Iterator wrappers = getWrappers(wrappee, null).iterator(); 706 Object ret = null; 707 MethodItem method = null; 708 Object wrapper = null; 709 710 while (wrappers.hasNext()) { 712 wrapper = wrappers.next(); 713 try { 714 method = 715 (MethodItem) ClassRepository.get().getClass( 716 wrapper).getAbstractMethods( 717 methodName)[0]; 718 } catch (org.objectweb.jac.core.rtti.NoSuchMethodException e) { 719 } 720 if (method != null) 721 break; 722 } 723 if (method == null) { 724 logger.warn( 725 "no such role method " + methodName 726 + " found on " + wrappee.getClass()); 727 return ret; 728 } 729 730 try { 731 732 Object [] actualParameters; 735 if (method.getParameterTypes().length > 0 736 && method.getParameterTypes()[0] == Wrappee.class) { 737 actualParameters = 738 new Object [method.getParameterTypes().length]; 739 actualParameters[0] = wrappee; 740 System.arraycopy( 741 parameters, 742 0, 743 actualParameters, 744 1, 745 actualParameters.length - 1); 746 } else { 747 actualParameters = parameters; 748 } 749 ret = method.invoke(wrapper, actualParameters); 751 752 } finally { 753 } 755 return ret; 756 } 757 758 768 public static Object invokeRoleMethod( 769 Wrappee wrappee, 770 Class wrapperClass, 771 String methodName, 772 Object [] parameters) 773 { 774 return invokeRoleMethod( 775 wrappee, 776 null, 777 wrapperClass, 778 methodName, 779 parameters); 780 } 781 782 793 794 public static Object invokeRoleMethod( 795 |