1 22 package org.jboss.ejb3; 23 24 import org.jboss.annotation.ejb.PoolClass; 25 import org.jboss.aop.AspectManager; 26 import org.jboss.aop.ClassAdvisor; 27 import org.jboss.aop.ClassContainer; 28 import org.jboss.aop.advice.Interceptor; 29 import org.jboss.aop.annotation.AnnotationElement; 30 import org.jboss.aop.joinpoint.ConstructorInvocation; 31 import org.jboss.aop.util.MethodHashing; 32 import org.jboss.ejb3.entity.PersistenceUnitDeployment; 33 import org.jboss.ejb3.interceptor.InterceptorInfo; 34 import org.jboss.ejb3.interceptor.InterceptorInfoRepository; 35 import org.jboss.ejb3.interceptor.InterceptorInjector; 36 import org.jboss.ejb3.interceptor.LifecycleInterceptorHandler; 37 import org.jboss.ejb3.metamodel.AssemblyDescriptor; 38 import org.jboss.ejb3.metamodel.EnterpriseBean; 39 import org.jboss.ejb3.security.JaccHelper; 40 import org.jboss.ejb3.statistics.InvocationStatistics; 41 import org.jboss.ejb3.tx.UserTransactionImpl; 42 import org.jboss.injection.DependsHandler; 43 import org.jboss.injection.EJBHandler; 44 import org.jboss.injection.EncInjector; 45 import org.jboss.injection.InjectionContainer; 46 import org.jboss.injection.InjectionHandler; 47 import org.jboss.injection.InjectionUtil; 48 import org.jboss.injection.Injector; 49 import org.jboss.injection.JndiInjectHandler; 50 import org.jboss.injection.PersistenceContextHandler; 51 import org.jboss.injection.PersistenceUnitHandler; 52 import org.jboss.injection.ResourceHandler; 53 import org.jboss.injection.WebServiceRefHandler; 54 import org.jboss.logging.Logger; 55 import org.jboss.metamodel.descriptor.PersistenceContextRef; 56 import org.jboss.metamodel.descriptor.EnvironmentRefGroup; 57 import org.jboss.naming.Util; 58 59 import javax.annotation.PostConstruct; 60 import javax.annotation.PreDestroy; 61 import javax.ejb.Local ; 62 import javax.ejb.Remote ; 63 import javax.ejb.Timeout ; 64 import javax.management.MalformedObjectNameException ; 65 import javax.management.ObjectName ; 66 import javax.naming.Context ; 67 import javax.naming.InitialContext ; 68 import javax.naming.LinkRef ; 69 import javax.naming.NameNotFoundException ; 70 import javax.naming.NamingException ; 71 72 import java.lang.annotation.Annotation ; 73 import java.lang.annotation.Retention ; 74 import java.lang.annotation.RetentionPolicy ; 75 import java.lang.reflect.AccessibleObject ; 76 import java.lang.reflect.Constructor ; 77 import java.lang.reflect.Field ; 78 import java.lang.reflect.InvocationTargetException ; 79 import java.lang.reflect.Method ; 80 import java.util.ArrayList ; 81 import java.util.Collection ; 82 import java.util.HashMap ; 83 import java.util.HashSet ; 84 import java.util.Hashtable ; 85 import java.util.LinkedHashSet ; 86 import java.util.List ; 87 import java.util.Map ; 88 89 95 public abstract class EJBContainer extends ClassContainer implements Container, InjectionContainer 96 { 97 98 private static final Logger log = Logger.getLogger(EJBContainer.class); 99 100 protected Pool pool; 101 102 protected String ejbName; 103 104 protected ObjectName objectName; 105 106 protected int defaultConstructorIndex; 107 108 protected String beanClassName; 109 110 protected ClassLoader classloader; 111 112 protected List <Injector> injectors = new ArrayList <Injector>(); 114 115 protected Context enc; 116 protected Context encEnv; 117 118 protected Class beanContextClass; 119 120 protected LifecycleInterceptorHandler callbackHandler; 122 123 protected Hashtable initialContextProperties; 124 125 protected Map <String , EncInjector> encInjectors = new HashMap <String , EncInjector>(); 126 127 protected EnterpriseBean xml; 128 protected AssemblyDescriptor assembly; 129 130 protected Map <String , Map <AccessibleObject , Injector>> encInjections = new HashMap <String , Map <AccessibleObject , Injector>>(); 131 132 protected InterceptorInfoRepository interceptorRepository; 133 134 protected List <InterceptorInfo> classInterceptors = new ArrayList <InterceptorInfo>(); 135 136 protected LinkedHashSet <InterceptorInfo> applicableInterceptors; 137 138 private HashMap <Class , InterceptorInjector> interceptorInjectors = new HashMap <Class , InterceptorInjector>(); 139 140 private Ejb3Deployment deployment; 141 142 private DependencyPolicy dependencyPolicy; 143 144 private String jaccContextId; 145 146 protected HashMap invokedMethod = new HashMap (); 147 148 protected InvocationStatistics invokeStats = new InvocationStatistics(); 149 150 160 161 public EJBContainer(String name, AspectManager manager, ClassLoader cl, 162 String beanClassName, String ejbName, Hashtable ctxProperties, 163 InterceptorInfoRepository interceptorRepository, Ejb3Deployment deployment) 164 { 165 super(name, manager); 166 this.deployment = deployment; 167 this.beanClassName = beanClassName; 168 this.classloader = cl; 169 try 170 { 171 clazz = classloader.loadClass(beanClassName); 172 } 173 catch (ClassNotFoundException e) 174 { 175 throw new RuntimeException (e); 176 } 177 this.ejbName = ejbName; 178 String on = Ejb3Module.BASE_EJB3_JMX_NAME + deployment.getScopeKernelName() + ",name=" + ejbName; 179 try 180 { 181 objectName = new ObjectName (on); 182 } 183 catch (MalformedObjectNameException e) 184 { 185 throw new RuntimeException ("failed to create object name for: " + on, e); 186 } 187 initialContextProperties = ctxProperties; 188 Context ctx = getInitialContext(); 189 try 190 { 191 enc = ThreadLocalENCFactory.create(ctx); 192 encEnv = Util.createSubcontext(enc, "env"); 193 } 194 catch (Exception e) 195 { 196 throw new RuntimeException (e); 197 } 198 this.interceptorRepository = interceptorRepository; 199 this.interceptorRepository.addBeanClass(clazz.getName()); 200 } 201 202 public EnvironmentRefGroup getEnvironmentRefGroup() 203 { 204 return xml; 205 } 206 207 public List <Injector> getInjectors() 208 { 209 return injectors; 210 } 211 212 213 public String getJaccContextId() 214 { 215 return jaccContextId; 216 } 217 218 public void setJaccContextId(String jaccContextId) 219 { 220 this.jaccContextId = jaccContextId; 221 } 222 223 public Ejb3Deployment getDeployment() 224 { 225 return deployment; 226 } 227 228 public DependencyPolicy getDependencyPolicy() 229 { 230 return dependencyPolicy; 231 } 232 233 238 public void instantiated() 239 { 240 241 } 242 243 251 public void processMetadata(DependencyPolicy dependencyPolicy) 252 { 253 this.dependencyPolicy = dependencyPolicy; 254 256 Collection <InjectionHandler> handlers = new ArrayList <InjectionHandler>(); 258 handlers.add(new EJBHandler()); 259 handlers.add(new DependsHandler()); 260 handlers.add(new JndiInjectHandler()); 261 handlers.add(new PersistenceContextHandler()); 262 handlers.add(new PersistenceUnitHandler()); 263 handlers.add(new ResourceHandler()); 264 handlers.add(new WebServiceRefHandler()); 265 266 ClassLoader old = Thread.currentThread().getContextClassLoader(); 267 Thread.currentThread().setContextClassLoader(classloader); 268 try 269 { 270 for (InjectionHandler handler : handlers) handler.loadXml(xml, this); 272 273 Map <AccessibleObject , Injector> tmp = InjectionUtil.processAnnotations(this, handlers, getBeanClass()); 274 injectors.addAll(tmp.values()); 275 276 initialiseInterceptors(); 277 for (InterceptorInfo interceptorInfo : applicableInterceptors) 278 { 279 for (InjectionHandler handler : handlers) 280 { 281 handler.loadXml(interceptorInfo.getXml(), this); 282 } 283 } 284 for (InterceptorInfo interceptorInfo : applicableInterceptors) 285 { 286 Map <AccessibleObject , Injector> tmpInterceptor = InjectionUtil.processAnnotations(this, handlers, interceptorInfo.getClazz()); 287 InterceptorInjector injector = new InterceptorInjector(this, interceptorInfo, tmpInterceptor); 288 interceptorInjectors.put(interceptorInfo.getClazz(), injector); 289 } 290 } 291 finally 292 { 293 Thread.currentThread().setContextClassLoader(old); 294 } 295 } 296 297 public EnterpriseBean getXml() 298 { 299 return xml; 300 } 301 302 public void setXml(EnterpriseBean xml) 303 { 304 this.xml = xml; 305 } 306 307 public AssemblyDescriptor getAssemblyDescriptor() 308 { 309 return assembly; 310 } 311 312 public void setAssemblyDescriptor(AssemblyDescriptor assembly) 313 { 314 this.assembly = assembly; 315 } 316 317 public InterceptorInfoRepository getInterceptorRepository() 318 { 319 return interceptorRepository; 320 } 321 322 public List <InterceptorInfo> getClassInterceptors() 323 { 324 initialiseInterceptors(); 325 return classInterceptors; 326 } 327 328 public HashSet <InterceptorInfo> getApplicableInterceptors() 329 { 330 initialiseInterceptors(); 331 return applicableInterceptors; 332 } 333 334 public HashMap <Class , InterceptorInjector> getInterceptorInjectors() 335 { 336 initialiseInterceptors(); 337 return interceptorInjectors; 338 } 339 340 341 public Map <String , EncInjector> getEncInjectors() 342 { 343 return encInjectors; 344 } 345 346 public ClassLoader getClassloader() 347 { 348 return classloader; 349 } 350 351 public InitialContext getInitialContext() 352 { 353 try 354 { 355 if (initialContextProperties == null) 356 return new InitialContext (); 357 else 358 return new InitialContext (initialContextProperties); 359 } 360 catch (NamingException e) 361 { 362 throw new RuntimeException (e); 363 } 364 } 365 366 public Map <String , Map <AccessibleObject , Injector>> getEncInjections() 367 { 368 return encInjections; 369 } 370 371 public Context getEnc() 372 { 373 return enc; 374 } 375 376 public Context getEncEnv() 377 { 378 return enc; 379 } 380 381 public Hashtable getInitialContextProperties() 382 { 383 return initialContextProperties; 384 } 385 386 public ObjectName getObjectName() 387 { 388 return objectName; 389 } 390 391 public String getEjbName() 392 { 393 return ejbName; 394 } 395 396 public String getBeanClassName() 397 { 398 return beanClassName; 399 } 400 401 public Class getBeanClass() 402 { 403 return clazz; 404 } 405 406 public Pool getPool() 407 { 408 return pool; 409 } 410 411 public Object construct() 412 { 413 Interceptor[] cInterceptors = constructorInterceptors[defaultConstructorIndex]; 414 if (cInterceptors == null) 415 { 416 try 417 { 418 return constructors[defaultConstructorIndex].newInstance(); 419 } 420 catch (InstantiationException e) 421 { 422 throw new RuntimeException (e); 423 } 424 catch (IllegalAccessException e) 425 { 426 throw new RuntimeException (e); 427 } 428 catch (InvocationTargetException e) 429 { 430 throw new RuntimeException (e); 431 } 432 } 433 ConstructorInvocation invocation = new ConstructorInvocation( 434 cInterceptors); 435 436 invocation.setAdvisor(this); 437 invocation.setConstructor(constructors[defaultConstructorIndex]); 438 try 439 { 440 return invocation.invokeNext(); 441 } 442 catch (Throwable throwable) 443 { 444 throw new RuntimeException (throwable); 445 } 446 447 } 448 449 public void create() throws Exception 450 { 451 initializeClassContainer(); 453 for (int i = 0; i < constructors.length; i++) 454 { 455 if (constructors[i].getParameterTypes().length == 0) 456 { 457 defaultConstructorIndex = i; 458 break; 459 } 460 } 461 } 462 463 public void start() throws Exception 465 { 466 initializePool(); 467 468 for (EncInjector injector : encInjectors.values()) 469 { 470 injector.inject(this); 471 } 472 473 477 Injector[] injectors2 = injectors.toArray(new Injector[injectors.size()]); 478 if (pool != null) pool.setInjectors(injectors2); 479 480 createCallbackHandler(); 481 482 JaccHelper.configureContainer(jaccContextId, this); 483 log.info("STARTED EJB: " + clazz.getName() + " ejbName: " + ejbName); 484 } 485 486 public void stop() throws Exception 487 { 488 } 489 490 public void destroy() throws Exception 491 { 492 } 493 494 public void initializePool() throws Exception 495 { 496 PoolClass poolClass = (PoolClass) resolveAnnotation(PoolClass.class); 497 Class poolClazz = poolClass.value(); 498 int maxSize = poolClass.maxSize(); 499 long timeout = poolClass.timeout(); 500 pool = (Pool) poolClazz.newInstance(); 501 pool.initialize(this, beanContextClass, clazz, maxSize, timeout); 502 503 resolveInjectors(); 504 pool.setInjectors(injectors.toArray(new Injector[injectors.size()])); 505 } 506 507 public void invokePostConstruct(BeanContext beanContext) 508 { 509 callbackHandler.postConstruct(beanContext); 510 } 511 512 public void invokePreDestroy(BeanContext beanContext) 513 { 514 callbackHandler.preDestroy(beanContext); 515 } 516 517 public void invokePostActivate(BeanContext beanContext) 518 { 519 throw new RuntimeException ("PostActivate not implemented for container"); 520 } 521 522 public void invokePrePassivate(BeanContext beanContext) 523 { 524 throw new RuntimeException ("PostActivate not implemented for container"); 525 } 526 527 public void invokeInit(Object bean) 528 { 529 530 } 531 532 public void invokeInit(Object bean, Class [] initParameterTypes, 533 Object [] initParameterValues) 534 { 535 536 } 537 538 public static final String MANAGED_ENTITY_MANAGER_FACTORY = "ManagedEntityManagerFactory"; 539 540 public static final String ENTITY_MANAGER_FACTORY = "EntityManagerFactory"; 541 542 protected void resolveInjectors() throws Exception 543 { 544 ThreadLocalENCFactory.push(enc); 545 try 546 { 547 Thread.currentThread().setContextClassLoader(classloader); 548 try 549 { 550 Util.rebind(enc, "UserTransaction", new UserTransactionImpl()); 551 } 552 catch (NamingException e) 553 { 554 NamingException namingException = new NamingException ("Could not bind user transaction for ejb name " + ejbName + " into JNDI under jndiName: " + enc.getNameInNamespace() + "/" + "UserTransaction"); 555 namingException.setRootCause(e); 556 throw namingException; 557 } 558 } 559 finally 560 { 561 ThreadLocalENCFactory.pop(); 562 } 563 } 564 565 protected void createCallbackHandler() 566 { 567 try 568 { 569 callbackHandler = new LifecycleInterceptorHandler(this, 570 getHandledCallbacks()); 571 } 572 catch (Exception e) 573 { 574 throw new RuntimeException ("Error creating callback handler for bean " 575 + beanClassName, e); 576 } 577 } 578 579 protected Class [] getHandledCallbacks() 580 { 581 return new Class [] 582 {PostConstruct.class, PreDestroy.class, Timeout .class}; 583 } 584 585 private void initialiseInterceptors() 586 { 587 if (applicableInterceptors == null) 588 { 589 log.debug("Initialising interceptors for " + getEjbName() + "..."); 590 HashSet <InterceptorInfo> defaultInterceptors = interceptorRepository.getDefaultInterceptors(); 591 log.debug("Default interceptors: " + defaultInterceptors); 592 593 classInterceptors = interceptorRepository.getClassInterceptors(this); 594 log.debug("Class interceptors: " + classInterceptors); 595 596 applicableInterceptors = new LinkedHashSet <InterceptorInfo>(); 597 if (defaultInterceptors != null) applicableInterceptors.addAll(defaultInterceptors); 598 if (classInterceptors != null) applicableInterceptors.addAll(classInterceptors); 599 600 Method [] methods = clazz.getMethods(); 601 for (int i = 0; i < methods.length; i++) 602 { 603 List methodIcptrs = interceptorRepository.getMethodInterceptors(this, methods[i]); 604 if (methodIcptrs != null && methodIcptrs.size() > 0) 605 { 606 log.debug("Method interceptors for " + methods[i] + ": " + methodIcptrs); 607 applicableInterceptors.addAll(methodIcptrs); 608 } 609 } 610 log.debug("All applicable interceptor classes: " + applicableInterceptors); 611 } 612 } 613 614 public Object getBusinessObject(BeanContext beanContext, Class businessObject) throws IllegalStateException 615 { 616 throw new IllegalStateException ("Not implemented"); 617 } 618 619 public Object getInvokedBusinessInterface(BeanContext beanContext) throws IllegalStateException 620 { 621 throw new IllegalStateException ("Not implemented"); 622 } 623 624 protected Object getInvokedInterface(Method method) 625 { 626 Remote remoteAnnotation = (Remote ) resolveAnnotation(Remote .class); 627 if (remoteAnnotation != null) 628 { 629 Class [] remotes = remoteAnnotation.value(); 630 for (int i = 0; i < remotes.length; ++i) 631 { 632 try 633 { 634 remotes[i].getMethod(method.getName(), method.getParameterTypes()); 635 return remotes[i]; 636 } 637 catch (NoSuchMethodException e) 638 { 639 } 640 } 641 } 642 643 Local localAnnotation = (Local ) resolveAnnotation(Local .class); 644 if (localAnnotation != null) 645 { 646 Class [] locals = localAnnotation.value(); 647 for (int i = 0; i < locals.length; ++i) 648 { 649 Method [] interfaceMethods = locals[i].getMethods(); 650 for (int j = 0; j < interfaceMethods.length; ++j) 651 { 652 if (interfaceMethods[j].equals(method)) 653 return locals[i]; 654 } 655 } 656 } 657 658 return null; 659 } 660 661 private Class loadPublicAnnotation(String annotation) 663 { 664 try 665 { 666 Class ann = classloader.loadClass(annotation); 667 if (!ann.isAnnotation()) return null; 668 Retention retention = (Retention ) ann.getAnnotation(Retention .class); 669 if (retention != null && retention.value() == RetentionPolicy.RUNTIME) return ann; 670 671 } 672 catch (ClassNotFoundException ignored) 673 { 674 } 675 return null; 676 } 677 678 @Override 679 public boolean hasAnnotation(Class tgt, String annotation) 680 { 681 if (annotations.hasClassAnnotation(annotation)) return true; 682 if (tgt == null) return false; 683 try 684 { 685 Class ann = loadPublicAnnotation(annotation); 686 if (ann == null) return AnnotationElement.isAnyAnnotationPresent(tgt, annotation); 688 return tgt.isAnnotationPresent(ann); 689 } 690 catch (Exception e) 691 { 692 throw new RuntimeException (e); } 694 } 695 696 697 @Override 698 public boolean hasAnnotation(Method m, String annotation) 699 { 700 if (annotations.hasAnnotation(m, annotation)) return true; 701 try 702 { 703 Class ann = loadPublicAnnotation(annotation); 704 if (ann == null) return AnnotationElement.isAnyAnnotationPresent(m, annotation); 706 return m.isAnnotationPresent(ann); 707 } 708 catch (Exception e) 709 { 710 throw new RuntimeException (e); } 712 } 713 714 @Override 715 public boolean hasAnnotation(Field m, String annotation) 716 { 717 if (annotations.hasAnnotation(m, annotation)) return true; 718 try 719 { 720 Class ann = loadPublicAnnotation(annotation); 721 if (ann == null) return AnnotationElement.isAnyAnnotationPresent(m, annotation); 723 return m.isAnnotationPresent(ann); 724 } 725 catch (Exception e) 726 { 727 throw new RuntimeException (e); } 729 } 730 731 @Override 732 public boolean hasAnnotation(Constructor m, String annotation) 733 { 734 if (annotations.hasAnnotation(m, annotation)) return true; 735 try 736 { 737 Class ann = loadPublicAnnotation(annotation); 738 if (ann == null) return AnnotationElement.isAnyAnnotationPresent(m, annotation); 740 return m.isAnnotationPresent(ann); 741 } 742 catch (Exception e) 743 { 744 throw new RuntimeException (e); } 746 } 747 748 public Container resolveEjbContainer(String link, Class businessIntf) 749 { 750 return deployment.getEjbContainer(link, businessIntf); 751 } 752 753 public Container resolveEjbContainer(Class businessIntf) throws NameNotFoundException 754 { 755 return deployment.getEjbContainer(businessIntf); 756 } 757 758 public <T extends Annotation > T getAnnotation(Class <T> annotationType, Class <?> clazz) 759 { 760 if (clazz == this.getBeanClass()) 761 { 762 return (T) resolveAnnotation(annotationType); 763 } 764 return clazz.getAnnotation(annotationType); 765 } 766 767 public <T extends Annotation > T getAnnotation(Class <T> annotationType, Class <?> clazz, Method method) 768 { 769 if (clazz == this.getBeanClass()) 770 { 771 return (T) resolveAnnotation(method, annotationType); 772 } 773 return method.getAnnotation(annotationType); 774 } 775 776 public <T extends Annotation > T getAnnotation(Class <T> annotationType, Method method) 777 { 778 return (T) resolveAnnotation(method, annotationType); 779 } 780 781 public <T extends Annotation > T getAnnotation(Class <T> annotationType, Class <?> clazz, Field field) 782 { 783 if (clazz == this.getBeanClass()) 784 { 785 return (T) resolveAnnotation(field, annotationType); 786 } 787 return field.getAnnotation(annotationType); 788 } 789 790 public <T extends Annotation > T getAnnotation(Class <T> annotationType, Field field) 791 { 792 return (T) resolveAnnotation(field, annotationType); 793 } 794 795 @Override 796 public Object resolveAnnotation(Method m, Class annotation) 797 { 798 Object value = super.resolveAnnotation(m, annotation); 799 if (value == null && m.isBridge()) value = getBridgedAnnotation(m, annotation); 800 return value; 801 } 802 803 protected Object getBridgedAnnotation(Method bridgeMethod, Class annotation) 804 { 805 Method [] methods = bridgeMethod.getDeclaringClass().getMethods(); 806 int i = 0; 807 boolean found = false; 808 Class [] bridgeParams = bridgeMethod.getParameterTypes(); 809 while (i < methods.length && !found) 810 { 811 if (!methods[i].isBridge() && methods[i].getName().equals(bridgeMethod.getName())) 812 { 813 Class [] params = methods[i].getParameterTypes(); 814 if (params.length == bridgeParams.length) 815 { 816 int j = 0; 817 boolean matches = true; 818 while (j < params.length && matches) 819 { 820 if (!bridgeParams[j].isAssignableFrom(params[j])) 821 matches = false; 822 ++j; 823 } 824 825 if (matches) 826 return resolveAnnotation(methods[i], annotation); 827 } 828 } 829 ++i; 830 } 831 832 return null; 833 } 834 835 public Object resolveAnnotation(Method m, Class [] annotationChoices) 836 { 837 Object value = null; 838 int i = 0; 839 while (value == null && i < annotationChoices.length){ 840 value = resolveAnnotation(m, annotationChoices[i++]); 841 } 842 843 return value; 844 } 845 846 public String getIdentifier() 847 { 848 return getEjbName(); 849 } 850 851 public String getDeploymentDescriptorType() 852 { 853 return "ejb-jar.xml"; 854 } 855 856 public PersistenceUnitDeployment getPersistenceUnitDeployment(String unitName) throws NameNotFoundException 857 { 858 return deployment.getPersistenceUnitDeployment(unitName); 859 } 860 861 public String getEjbJndiName(Class businessInterface) throws NameNotFoundException 862 { 863 return deployment.getEjbJndiName(businessInterface); 864 } 865 866 public String getEjbJndiName(String link, Class businessInterface) 867 { 868 return deployment.getEjbJndiName(link, businessInterface); 869 } 870 871 public InvocationStatistics getInvokeStats() 872 { 873 return invokeStats; 874 } 875 } 876 | Popular Tags |