1 22 package org.jboss.ejb3.interceptor; 23 24 import org.jboss.ejb3.EJBContainer; 25 import org.jboss.ejb3.metamodel.EjbJarDD; 26 import org.jboss.ejb3.metamodel.Interceptor; 27 import org.jboss.ejb3.metamodel.InterceptorBinding; 28 import org.jboss.ejb3.metamodel.Interceptors; 29 import org.jboss.logging.Logger; 30 31 import javax.annotation.PostConstruct; 32 import javax.annotation.PreDestroy; 33 import javax.ejb.PostActivate ; 34 import javax.ejb.PrePassivate ; 35 import javax.interceptor.AroundInvoke; 36 import javax.interceptor.ExcludeClassInterceptors; 37 import javax.interceptor.ExcludeDefaultInterceptors; 38 import javax.interceptor.InvocationContext; 39 import java.lang.annotation.Annotation ; 40 import java.lang.reflect.Method ; 41 import java.lang.reflect.Modifier ; 42 import java.util.*; 43 import java.util.concurrent.ConcurrentHashMap ; 44 import java.util.concurrent.ConcurrentMap ; 45 46 58 public class InterceptorInfoRepository 59 { 60 private static Logger log = Logger.getLogger(InterceptorInfoRepository.class); 61 62 private Set<String > beanClasses = new HashSet<String >(); 63 64 private Interceptors interceptorsXml; 65 66 private List<InterceptorBinding> bindingsXml; 67 68 private ConcurrentMap <Class , InterceptorInfo> infos = new ConcurrentHashMap <Class , InterceptorInfo>(); 69 70 private ConcurrentMap <String , InterceptorInfo> ejbInfos = new ConcurrentHashMap <String , InterceptorInfo>(); 71 72 private LinkedHashSet<InterceptorInfo> defaultInterceptors = null; 73 74 private InterceptorSorter sorter = new InterceptorSorter(); 75 76 public InterceptorInfoRepository() 77 { 78 } 79 80 public void initialise(EjbJarDD dd) 81 { 82 this.interceptorsXml = dd.getInterceptors(); 83 84 if (dd.getAssemblyDescriptor() != null) 85 { 86 this.bindingsXml = dd.getAssemblyDescriptor().getInterceptorBindings(); 87 } 88 89 initialiseInfosFromXml(); 90 initialiseDefaultInterceptors(); 91 } 92 93 public void addBeanClass(String classname) 94 { 95 beanClasses.add(classname); 96 } 97 98 public InterceptorInfo getInterceptorInfo(Class clazz) 99 { 100 initialiseInfosFromXml(); 101 return infos.get(clazz); 102 } 103 104 public HashSet<InterceptorInfo> getDefaultInterceptors() 105 { 106 return defaultInterceptors; 107 } 108 109 public boolean hasDefaultInterceptors() 110 { 111 return defaultInterceptors.size() > 0; 112 } 113 114 public ArrayList<InterceptorInfo> getClassInterceptors(EJBContainer container) 115 { 116 javax.interceptor.Interceptors interceptors = (javax.interceptor.Interceptors) container 117 .resolveAnnotation(javax.interceptor.Interceptors.class); 118 ArrayList<InterceptorInfo> infos = getInterceptorsFromAnnotation(container, interceptors); 119 120 return infos; 121 } 122 123 public ArrayList<InterceptorInfo> getMethodInterceptors(EJBContainer container, Method m) 124 { 125 javax.interceptor.Interceptors interceptors = (javax.interceptor.Interceptors) container.resolveAnnotation(m, 126 javax.interceptor.Interceptors.class); 127 ArrayList<InterceptorInfo> infos = getInterceptorsFromAnnotation(container, interceptors); 128 129 return infos; 130 } 131 132 public Method [] getBeanClassAroundInvokes(EJBContainer container) 133 { 134 return getBeanClassInterceptors(container, AroundInvoke.class); 135 } 136 137 public Method [] getBeanClassPostConstructs(EJBContainer container) 138 { 139 return getBeanClassInterceptors(container, PostConstruct.class); 140 } 141 142 public Method [] getBeanClassPostActivates(EJBContainer container) 143 { 144 return getBeanClassInterceptors(container, PostActivate .class); 145 } 146 147 public Method [] getBeanClassPrePassivates(EJBContainer container) 148 { 149 return getBeanClassInterceptors(container, PrePassivate .class); 150 } 151 152 public Method [] getBeanClassPreDestroys(EJBContainer container) 153 { 154 return getBeanClassInterceptors(container, PreDestroy.class); 155 } 156 157 private Method [] getBeanClassInterceptors(EJBContainer container, Class type) 158 { 159 InterceptorInfo info = getOrInitialiseFromAnnotations(container); 160 return getMethodsForEvent(info, type); 161 } 162 163 public InterceptorInfo[] getBusinessInterceptors(EJBContainer container, Method method) 164 { 165 return getInterceptors(container, AroundInvoke.class, method); 166 } 167 168 public InterceptorInfo[] getPostConstructInterceptors(EJBContainer container) 169 { 170 return getInterceptors(container, PostConstruct.class, null); 171 } 172 173 public InterceptorInfo[] getPostActivateInterceptors(EJBContainer container) 174 { 175 return getInterceptors(container, PostActivate .class, null); 176 } 177 178 public InterceptorInfo[] getPrePassivateInterceptors(EJBContainer container) 179 { 180 return getInterceptors(container, PrePassivate .class, null); 181 } 182 183 public InterceptorInfo[] getPreDestroyInterceptors(EJBContainer container) 184 { 185 return getInterceptors(container, PreDestroy.class, null); 186 } 187 188 private InterceptorInfo[] getInterceptors(EJBContainer container, Class type, Method method) 189 { 190 ArrayList<InterceptorInfo> interceptors = new ArrayList<InterceptorInfo>(); 191 192 if (!hasAnnotation(container, ExcludeDefaultInterceptors.class, method)) 193 { 194 HashSet<InterceptorInfo> infos = getDefaultInterceptors(); 195 if (infos != null) 196 { 197 interceptors.addAll(trimUnwanted(infos, type)); 198 } 199 sorter.sortDefaultInterceptors(container, interceptors); 200 } 201 202 203 if (!hasAnnotation(container, ExcludeClassInterceptors.class, method)) 204 { 205 List<InterceptorInfo> infos = container.getClassInterceptors(); 206 if (infos != null) 207 { 208 interceptors.addAll(trimUnwanted(infos, type)); 209 } 210 211 if (type != AroundInvoke.class) 212 { 213 List<InterceptorInfo> methodOnlyInterceptors = getMethodOnlyInterceptorsForLifecycle(container, type, interceptors); 214 if (infos != null) 215 interceptors.addAll(methodOnlyInterceptors); 216 } 217 sorter.sortClassInterceptors(container, interceptors); 218 } 219 220 if (type == AroundInvoke.class) 221 { 222 List<InterceptorInfo> infos = getMethodInterceptors(container, method); 223 if (infos != null) 224 interceptors.addAll(trimUnwanted(infos, type)); 225 sorter.sortMethodInterceptors(container, method, interceptors); 226 } 227 228 InterceptorInfo[] ints = interceptors.toArray(new InterceptorInfo[interceptors.size()]); 229 return ints; 230 } 231 232 private List<InterceptorInfo> getMethodOnlyInterceptorsForLifecycle(EJBContainer container, Class type, List<InterceptorInfo> infos) 233 { 234 HashSet<InterceptorInfo> methodLevelInterceptors = (HashSet<InterceptorInfo>)container.getApplicableInterceptors().clone(); 235 236 for (InterceptorInfo info : infos) 237 { 238 if (methodLevelInterceptors.contains(info)) 239 { 240 methodLevelInterceptors.remove(info); 241 } 242 } 243 244 if (defaultInterceptors != null) 245 { 246 for (InterceptorInfo info : defaultInterceptors) 247 { 248 if (methodLevelInterceptors.contains(info)) 249 { 250 methodLevelInterceptors.remove(info); 251 } 252 } 253 } 254 255 List<InterceptorInfo> trimmedInfos = trimUnwanted(methodLevelInterceptors, type); 256 return trimmedInfos; 257 } 258 259 private boolean hasAnnotation(EJBContainer container, Class annotation, Method method) 260 { 261 if (container.resolveAnnotation(annotation) != null) 262 { 263 return true; 264 } 265 266 if (method != null) 267 { 268 return container.resolveAnnotation(method, annotation) != null; 269 } 270 271 return false; 272 } 273 274 private List<InterceptorInfo> trimUnwanted(Collection<InterceptorInfo> interceptors, Class type) 275 { 276 ArrayList<InterceptorInfo> ints = new ArrayList<InterceptorInfo>(interceptors.size()); 277 ints.addAll(interceptors); 278 279 for (Iterator<InterceptorInfo> it = ints.iterator(); it.hasNext();) 280 { 281 InterceptorInfo info = it.next(); 282 if (!hasMethodsForEvent(info, type)) 283 { 284 it.remove(); 285 } 286 } 287 288 return ints; 289 } 290 291 private boolean hasMethodsForEvent(InterceptorInfo info, Class type) 292 { 293 return getMethodsForEvent(info, type) != null; 294 } 295 296 private Method [] getMethodsForEvent(InterceptorInfo info, Class type) 297 { 298 if (type == AroundInvoke.class) 299 return info.getAroundInvokes(); 300 else if (type == PostConstruct.class) 301 return info.getPostConstructs(); 302 else if (type == PostActivate .class) 303 return info.getPostActivates(); 304 else if (type == PrePassivate .class) 305 return info.getPrePassivates(); 306 else if (type == PreDestroy.class) 307 return info.getPreDestroys(); 308 return null; 309 } 310 311 private ArrayList<InterceptorInfo> getInterceptorsFromAnnotation(EJBContainer container, 312 javax.interceptor.Interceptors interceptors) 313 { 314 ArrayList<InterceptorInfo> inters = new ArrayList<InterceptorInfo>(); 315 if (interceptors == null) 316 return inters; 317 318 for (Class clazz : interceptors.value()) 319 { 320 InterceptorInfo info = getOrInitialiseFromAnnotations(clazz); 321 validateInterceptorForContainer(container, info.getClazz()); 322 inters.add(info); 323 } 324 325 return inters; 326 } 327 328 private void validateInterceptorForContainer(EJBContainer container, Class interceptor) 329 { 330 if (beanClasses.contains(interceptor.getName())) 331 { 332 if (!interceptor.equals(container.getClazz())) 333 { 334 throw new RuntimeException ("Bean class " + interceptor.getName() + " cannot be used as an interceptor for " 335 + container.getEjbName()); 336 } 337 } 338 } 339 340 private void initialiseInfosFromXml() 341 { 342 if (interceptorsXml != null) 343 { 344 HashMap <String , AnnotationInitialiser> initialisers = new HashMap <String , AnnotationInitialiser>(); 346 for (Interceptor xml : interceptorsXml.getInterceptors()) 347 { 348 XmlInitialiser init = new XmlInitialiser(xml); 349 initialisers.put(xml.getInterceptorClass(), init); 350 } 351 352 for (Interceptor xml : interceptorsXml.getInterceptors()) 354 { 355 String clazz = xml.getInterceptorClass(); 356 initialiseSuperClassesFirstFromXmlOrAnnotations(initialisers, clazz); 357 } 358 359 } 360 } 361 362 private InterceptorInfo initialiseSuperClassesFirstFromXmlOrAnnotations( 363 HashMap <String , AnnotationInitialiser> initialisers, String superClassName) 364 { 365 if ("java.lang.Object".equals(superClassName)) 366 { 367 return null; 368 } 369 370 AnnotationInitialiser initialiser = initialisers.get(superClassName); 371 if (initialiser == null) 372 { 373 initialiser = new AnnotationInitialiser(superClassName, InterceptorSignatureValidator.instance); 374 initialisers.put(initialiser.getClazz().getName(), initialiser); 375 } 376 InterceptorInfo superInfo = initialiseSuperClassesFirstFromXmlOrAnnotations( 377 initialisers, initialiser.getClazz().getSuperclass().getName()); 378 379 InterceptorInfo info = initialiser.getInfo(); 380 info.calculateHierarchy(superInfo); 381 infos.put(info.getClazz(), info); 382 return info; 383 } 384 385 388 private void initialiseDefaultInterceptors() 389 { 390 defaultInterceptors = new LinkedHashSet<InterceptorInfo>(); 391 392 if (bindingsXml != null) 393 { 394 for (InterceptorBinding bindingXml : bindingsXml) 395 { 396 if (bindingXml.getEjbName().equals("*") 397 && (bindingXml.getMethodName() == null || bindingXml.getMethodName().length() == 0)) 398 { 399 for (String classname : bindingXml.getInterceptorClasses()) 400 { 401 if (beanClasses.contains(classname)) 402 { 403 throw new RuntimeException ("Bean class defined in default binding " + classname); 404 } 405 InterceptorInfo info = getOrInitialiseFromAnnotations(classname); 406 defaultInterceptors.add(info); 407 } 408 } 409 } 410 } 411 } 412 413 private InterceptorInfo getOrInitialiseFromAnnotations(String classname) 414 { 415 Class clazz = loadClass(classname); 416 return getOrInitialiseFromAnnotations(clazz); 417 } 418 419 private InterceptorInfo getOrInitialiseFromAnnotations(Class clazz) 420 { 421 InterceptorInfo info = infos.get(clazz); 422 423 if (info == null) 424 { 425 synchronized (this) 426 { 427 info = infos.get(clazz); 428 if (info == null) 429 { 430 info = initialiseFromAnnotations(clazz); 431 infos.put(clazz, info); 432 } 433 } 434 } 435 436 return info; 437 } 438 439 private InterceptorInfo initialiseFromAnnotations(Class clazz) 440 { 441 InterceptorInfo superInfo = null; 442 if (clazz.getSuperclass() != Object .class) 443 { 444 superInfo = getOrInitialiseFromAnnotations(clazz.getSuperclass()); 445 } 446 447 AnnotationInitialiser init = new AnnotationInitialiser(clazz, InterceptorSignatureValidator.instance); 448 InterceptorInfo info = init.getInfo(); 449 info.calculateHierarchy(superInfo); 450 return info; 451 } 452 453 private InterceptorInfo getOrInitialiseFromAnnotations(EJBContainer container) 454 { 455 InterceptorInfo info = ejbInfos.get(container.getEjbName()); 456 457 if (info == null) 458 { 459 synchronized (this) 460 { 461 info = ejbInfos.get(container.getEjbName()); 462 if (info == null) 463 { 464 info = initialiseFromAnnotations(container); 465 ejbInfos.put(container.getEjbName(), info); 466 } 467 } 468 } 469 470 return info; 471 } 472 473 private InterceptorInfo initialiseFromAnnotations(EJBContainer container) 474 { 475 InterceptorInfo superInfo = initialiseContainerSuperClassFromAnnotationsOnly(container.getClazz().getSuperclass()); 478 AnnotationInitialiser init = new ContainerInitialiser(container); 479 InterceptorInfo info = init.getInfo(); 480 info.calculateHierarchy(superInfo); 481 return info; 482 } 483 484 private InterceptorInfo initialiseContainerSuperClassFromAnnotationsOnly(Class clazz) 485 { 486 InterceptorInfo superInfo = null; 487 if (clazz != Object .class) 488 { 489 superInfo = initialiseContainerSuperClassFromAnnotationsOnly(clazz.getSuperclass()); 490 } 491 492 AnnotationInitialiser init = new AnnotationInitialiser(clazz, BeanSignatureValidator.instance); 493 InterceptorInfo info = init.getInfo(); 494 info.calculateHierarchy(superInfo); 495 return info; 496 } 497 498 499 private Class loadClass(String name) 500 { 501 try 502 { 503 return Thread.currentThread().getContextClassLoader().loadClass(name); 504 } 505 catch (Exception e) 506 { 507 throw new RuntimeException ("Interceptor class not found: " + name); 508 } 509 } 510 511 public static boolean checkValidBusinessSignature(Method method) 512 { 513 int modifiers = method.getModifiers(); 514 515 if (!Modifier.isStatic(modifiers)) 516 { 517 if (method.getReturnType().equals(Object .class)) 518 { 519 Class [] params = method.getParameterTypes(); 520 if (params.length == 1 && params[0].equals(InvocationContext.class)) 521 { 522 Class [] exceptions = method.getExceptionTypes(); 523 if (exceptions.length == 1 && exceptions[0].equals(Exception .class)) 524 { 525 return true; 526 } 527 } 528 } 529 } 530 return false; 531 } 532 533 public static boolean checkValidLifecycleSignature(Method method) 534 { 535 int modifiers = method.getModifiers(); 536 537 if (!Modifier.isStatic(modifiers)) 538 { 539 if (method.getReturnType().equals(Void.TYPE)) 540 { 541 Class [] params = method.getParameterTypes(); 542 if (params.length == 1 && params[0].equals(InvocationContext.class)) 543 { 544 return true; 545 } 546 } 547 } 548 return false; 549 } 550 551 public static boolean checkValidBeanLifecycleSignature(Method method) 552 { 553 int modifiers = method.getModifiers(); 554 if (method.getName().equals("ejbCreate")) 555 { 556 if (!Modifier.isStatic(modifiers) && method.getReturnType().equals(Void.TYPE) 558 && method.getParameterTypes().length == 0 && method.getExceptionTypes().length <= 1) 559 return true; 560 } 561 else if (!Modifier.isStatic(modifiers) && method.getReturnType().equals(Void.TYPE) 562 && method.getParameterTypes().length == 0 && method.getExceptionTypes().length == 0) 563 { 564 return true; 565 } 566 return false; 567 } 568 569 public static String simpleType(Class type) 570 { 571 Class ret = type; 572 if (ret.isArray()) 573 { 574 Class arr = ret; 575 String array = ""; 576 while (arr.isArray()) 577 { 578 array += "[]"; 579 arr = arr.getComponentType(); 580 } 581 return arr.getName() + array; 582 } 583 return ret.getName(); 584 } 585 586 587 private interface SignatureValidator 588 { 589 boolean checkValidLifecycle(Method m); 590 boolean checkValidAround(Method m); 591 } 592 593 private static class InterceptorSignatureValidator implements SignatureValidator 594 { 595 static SignatureValidator instance = new InterceptorSignatureValidator(); 596 public boolean checkValidAround(Method m) 597 { 598 return checkValidBusinessSignature(m); 599 } 600 601 public boolean checkValidLifecycle(Method m) 602 { 603 return checkValidLifecycleSignature(m); 604 } 605 } 606 607 private static class BeanSignatureValidator implements SignatureValidator 608 { 609 static SignatureValidator instance = new BeanSignatureValidator(); 610 public boolean checkValidAround(Method m) 611 { 612 return checkValidBusinessSignature(m); 613 } 614 615 public boolean checkValidLifecycle(Method m) 616 { 617 return checkValidBeanLifecycleSignature(m); 618 } 619 } 620 621 622 private class AnnotationInitialiser 623 { 624 SignatureValidator signatureValidator; 625 Class clazz; 626 627 InterceptorInfo info; 628 629 AnnotationInitialiser(String classname, SignatureValidator signatureValidator) 630 { 631 clazz = loadClass(classname); 632 this.signatureValidator = signatureValidator; 633 info = new InterceptorInfo(clazz); 634 } 635 636 AnnotationInitialiser(Class clazz, SignatureValidator signatureValidator) 637 { 638 this.clazz = clazz; 639 this.signatureValidator = signatureValidator; 640 info = new InterceptorInfo(clazz); 641 } 642 643 public Class getClazz() 644 { 645 return clazz; 646 } 647 648 InterceptorInfo getInfo() 649 { 650 for (Method method : clazz.getDeclaredMethods()) 651 { 652 info.setAroundInvoke(resolveAroundInvoke(method)); 653 info.setPostConstruct(resolvePostConstruct(method)); 654 info.setPostActivate(resolvePostActivate(method)); 655 info.setPreDestroy(resolvePreDestroy(method)); 656 info.setPrePassivate(resolvePrePassivate(method)); 657 } 658 return info; 659 } 660 661 Method resolveAroundInvoke(Method method) 662 { 663 AroundInvoke ann = (AroundInvoke) getAnnotation(method, AroundInvoke.class); 664 if (ann != null) 665 { 666 if (!signatureValidator.checkValidAround(method)) 667 { 668 throw new RuntimeException ("@" + ((Annotation ) ann).annotationType().getName() 669 + " annotated method in has the wrong signature - " + method); 670 } 671 return method; 672 } 673 return null; 674 } 675 676 Method resolvePostConstruct(Method method) 677 { 678 PostConstruct ann = (PostConstruct) getAnnotation(method, PostConstruct.class); 679 return resolveLifecycleMethod(method, ann); 680 } 681 682 Method resolvePostActivate(Method method) 683 { 684 PostActivate ann = (PostActivate ) getAnnotation(method, PostActivate .class); 685 return resolveLifecycleMethod(method, ann); 686 } 687 688 Method resolvePreDestroy(Method method) 689 { 690 PreDestroy ann = (PreDestroy) getAnnotation(method, PreDestroy.class); 691 return resolveLifecycleMethod(method, ann); 692 } 693 694 Method resolvePrePassivate(Method method) 695 { 696 PrePassivate ann = (PrePassivate ) getAnnotation(method, PrePassivate .class); 697 return resolveLifecycleMethod(method, ann); 698 } 699 700 Method resolveLifecycleMethod(Method method, Annotation ann) 701 { 702 if (ann != null) 703 { 704 if (!signatureValidator.checkValidLifecycle(method)) 705 { 706 throw new RuntimeException ("@" + ((Annotation ) ann).annotationType().getName() 707 + " annotated method has the wrong signature - " + method); 708 } 709 return method; 710 } 711 return null; 712 } 713 714 Object getAnnotation(Method method, Class annotation) 715 { 716 return method.getAnnotation(annotation); 717 } 718 719 } 720 721 private class ContainerInitialiser extends AnnotationInitialiser 722 { 723 EJBContainer container; 724 725 public ContainerInitialiser(EJBContainer container) 726 { 727 super(container.getBeanClass(), BeanSignatureValidator.instance); 729 this.container = container; 730 } 731 732 Object getAnnotation(Method method, Class annotation) 733 { 734 return container.resolveAnnotation(method, annotation); 735 } 736 737 741 Method resolveLifecycleMethod(Method method, Annotation ann) 742 { 743 if (ann != null) 744 { 745 if (!signatureValidator.checkValidLifecycle(method)) 746 { 747 if (ann.annotationType() == PostConstruct.class && method.getName().equals("ejbCreate")) 750 { 751 return method; 752 } 753 754 throw new RuntimeException ("@" + ann.annotationType().getName() 755 + " annotated method has the wrong signature - " + method); 756 } 757 return method; 758 } 759 return null; 760 } 761 } 762 763 private class XmlInitialiser extends AnnotationInitialiser 764 { 765 Interceptor xml; 766 767 XmlInitialiser(Interceptor xml) 768 { 769 super(xml.getInterceptorClass(), InterceptorSignatureValidator.instance); 770 this.xml = xml; 771 } 772 773 InterceptorInfo getInfo() 774 { 775 info.setAroundInvoke(findInterceptorMethodFromXml(clazz, "around-invoke-method", xml.getAroundInvoke())); 776 info.setPostConstruct(findInterceptorMethodFromXml(clazz, "post-construct-method", xml.getPostConstruct())); 777 info.setPostActivate(findInterceptorMethodFromXml(clazz, "post-activate-method", xml.getPostActivate())); 778 info.setPreDestroy(findInterceptorMethodFromXml(clazz, "pre-destroy-method", xml.getPreDestroy())); 779 info.setPrePassivate(findInterceptorMethodFromXml(clazz, "pre-passivate-method", xml.getPrePassivate())); 780 super.getInfo(); 781 info.setXml(xml); 782 return info; 783 } 784 785 java.lang.reflect.Method findInterceptorMethodFromXml(Class clazz, String lookingFor, org.jboss.ejb3.metamodel.Method xml) 786 { 787 if (xml == null) 788 return null; 789 if (xml.getMethodName() == null || xml.getMethodName().trim().equals("")) 790 { 791 throw new RuntimeException (lookingFor + " must contain a valid method name for interceptor " 792 + clazz.getName()); 793 } 794 if (xml.getMethodParams() != null) 795 { 796 log.debug("Ignoring method parameters for " + lookingFor + " in interceptor " + clazz.getName()); 797 } 798 799 ArrayList<Method > possible = new ArrayList<Method >(); 800 for (java.lang.reflect.Method method : clazz.getDeclaredMethods()) 801 { 802 if (xml.getMethodName().equals(method.getName())) 803 { 804 possible.add(method); 805 } 806 } 807 808 if (possible.size() == 0) 809 { 810 throw new RuntimeException (lookingFor + " must contain a valid method name for interceptor " 811 + clazz.getName()); 812 } 813 814 Method found = null; 815 816 for (Method method : possible) 817 { 818 if (lookingFor.equals("around-invoke-method")) 819 { 820 if (signatureValidator.checkValidAround(method)) 821 { 822 found = method; 823 } 824 } 825 else 826 { 827 if (signatureValidator.checkValidLifecycle(method)) 828 { 829 found = method; 830 } 831 } 832 } 833 834 if (found == null) 835 { 836 throw new RuntimeException (lookingFor + " has the wrong method signature for interceptor " 837 + clazz.getName()); 838 } 839 840 return found; 841 } 842 } 843 844 private class InterceptorSorter 845 { 846 boolean initialised; 847 List<InterceptorBinding> orderedBindings; 848 849 void initialise() 850 { 851 if (!initialised) 852 { 853 synchronized(this) 854 { 855 if (bindingsXml != null) 856 { 857 for (InterceptorBinding binding : bindingsXml) 858 { 859 if (binding.isOrdered()) 860 { 861 HashSet names = new HashSet(); 863 for (Iterator it = binding.getInterceptorClasses().iterator() ; it.hasNext() ; ) 864 { 865 String className = (String )it.next(); 866 if (names.contains(className)) 867 { 868 throw new RuntimeException (className + " occurs more than once in ordered binding " + 869 getInterceptorBindingString(binding)); 870 } 871 names.add(className); 872 } 873 874 if (orderedBindings == null) 875 { 876 orderedBindings = new ArrayList<InterceptorBinding>(); 877 } 878 orderedBindings.add(binding); 879 } 880 } 881 } 882 } 883 initialised = true; 884 } 885 } 886 887 void sortDefaultInterceptors(EJBContainer container, ArrayList<InterceptorInfo> infos) 888 { 889 initialise(); 890 if (orderedBindings == null) return; 891 ArrayList<String > bindingOrder = null; 892 for (InterceptorBinding binding : orderedBindings) 893 { 894 if (binding.getEjbName().equals("*")) 895 { 896 if (bindingOrder != null) 897 { 898 throw new RuntimeException ("There should only be one interceptor-binding specifying " + 899 "the order of default interceptors " + getInterceptorBindingString(binding)); 900 } 901 bindingOrder = binding.getInterceptorClasses(); 902 } 903 } 904 sortInterceptors(infos, bindingOrder); 905 } 906 907 void sortClassInterceptors(EJBContainer container, ArrayList<InterceptorInfo> infos) 908 { 909 initialise(); 910 if (orderedBindings == null) return; 911 ArrayList<String > bindingOrder = null; 912 for (InterceptorBinding binding : orderedBindings) 913 { 914 if (binding.getMethodName() != null && binding.getMethodName().trim().length() > 0) 915 { 916 continue; 917 } 918 if (binding.getEjbName().equals(container.getEjbName())) 919 { 920 if (bindingOrder != null) 921 { 922 throw new RuntimeException ("There should only be one interceptor-binding specifying " + 923 "the order of class interceptors: " + getInterceptorBindingString(binding)); 924 } 925 bindingOrder = binding.getInterceptorClasses(); 926 } 927 } 928 sortInterceptors(infos, bindingOrder); 929 } 930 931 void sortMethodInterceptors(EJBContainer container, Method method, ArrayList<InterceptorInfo> infos) 932 { 933 initialise(); 934 if (orderedBindings == null) return; 935 ArrayList<String > methodNoParamsOrder = null; 936 ArrayList<String > methodParamsOrder = null; 937 for (InterceptorBinding binding : orderedBindings) 938 { 939 if (binding.getEjbName().equals(container.getEjbName())) 940 { 941 if (binding.getMethodName() != null && binding.getMethodName().equals(method.getName())) 942 { 943 if (binding.getMethodParams() == null) 944 { 945 if (methodNoParamsOrder != null) 946 { 947 throw new RuntimeException ("There should only be one interceptor-binding specifying " + 948 "the order of method interceptors: " + getInterceptorBindingString(binding)); 949 } 950 methodNoParamsOrder = binding.getInterceptorClasses(); 951 } 952 else 953 { 954 Class [] params = method.getParameterTypes(); 955 List<String > methodParams = binding.getMethodParams(); 956 if (methodParams.size() == params.length) 957 { 958 boolean matches = true; 959 for (int i = 0 ; i < params.length ; i++) 960 { 961 if (!simpleType(params[i]).equals(methodParams.get(i))) 962 { 963 matches = false; 964 break; 965 } 966 } 967 968 if (matches) 969 { 970 if (methodParamsOrder != null) 971 { 972 boolean first = false; 973 StringBuffer paramBuf = new StringBuffer (); 974 paramBuf.append("("); 975 for (String par : methodParams) 976 { 977 if (!first) paramBuf.append(","); 978 paramBuf.append(par); 979 } 980 paramBuf.append(")"); 981 throw new RuntimeException ("There should only be one interceptor-binding specifying " + 982 "the order of method interceptors: " + getInterceptorBindingString(binding)); 983 } 984 985 methodParamsOrder = binding.getInterceptorClasses(); 986 } 987 } 988 } 989 } 990 } 991 } 992 993 if (methodParamsOrder != null) 994 { 995 sortInterceptors(infos, methodParamsOrder); 996 997 } 998 else 999 { 1000 sortInterceptors(infos, methodNoParamsOrder); 1001 } 1002 } 1003 1004 void sortInterceptors(ArrayList<InterceptorInfo> infos, ArrayList<String > interceptorOrder) 1005 { 1006 if (interceptorOrder == null) return; 1007 Collections.sort(infos, new InterceptorComparator(interceptorOrder)); 1008 } 1009 1010 String getInterceptorBindingString(InterceptorBinding binding) 1011 { 1012 StringBuffer buf = new StringBuffer (); 1013 List methodParams = binding.getMethodParams(); 1014 1015 buf.append(binding.getEjbName()); 1016 if (binding.getMethodName() != null) 1017 { 1018 buf.append("." + binding.getMethodName()); 1019 if (methodParams != null) 1020 { 1021 buf.append("("); 1022 for (int i = 0 ; i < methodParams.size() ; ) 1023 { 1024 if (i == 0) buf.append(","); 1025 buf.append((String )methodParams.get(i)); 1026 } 1027 buf.append(")"); 1028 } 1029 } 1030 1031 return buf.toString(); 1032 } 1033 } 1034 1035 private class InterceptorComparator implements Comparator<InterceptorInfo> 1036 { 1037 ArrayList<String > ordered; 1038 1039 InterceptorComparator(ArrayList<String > ordered) 1040 { 1041 this.ordered = ordered; 1042 } 1043 1044 public int compare(InterceptorInfo o1, InterceptorInfo o2) 1045 { 1046 int pos1 = ordered.indexOf(o1.getClazz().getName()); 1047 int pos2 = ordered.indexOf(o2.getClazz().getName()); 1048 1049 if (pos1 < 0) pos1 = Integer.MAX_VALUE; 1051 if (pos2 < 0) pos2 = Integer.MAX_VALUE; 1052 1053 if (pos1 < pos2) 1054 { 1055 return -1; 1056 } 1057 else if (pos1 > pos2) 1058 { 1059 return 1; 1060 } 1061 else 1062 { 1063 return 0; 1064 } 1065 } 1066 1067 1068 } 1069 1070} 1071 | Popular Tags |