001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.ejb3;
023:
024: import java.lang.annotation.Annotation;
025: import java.lang.annotation.Retention;
026: import java.lang.annotation.RetentionPolicy;
027: import java.lang.reflect.AccessibleObject;
028: import java.lang.reflect.Constructor;
029: import java.lang.reflect.Field;
030: import java.lang.reflect.InvocationTargetException;
031: import java.lang.reflect.Method;
032: import java.util.ArrayList;
033: import java.util.Collection;
034: import java.util.HashMap;
035: import java.util.HashSet;
036: import java.util.Hashtable;
037: import java.util.LinkedHashSet;
038: import java.util.List;
039: import java.util.Map;
040: import java.util.Set;
041:
042: import javax.annotation.PostConstruct;
043: import javax.annotation.PreDestroy;
044: import javax.ejb.Local;
045: import javax.ejb.Remote;
046: import javax.ejb.Timeout;
047: import javax.management.MalformedObjectNameException;
048: import javax.management.ObjectName;
049: import javax.naming.Context;
050: import javax.naming.InitialContext;
051: import javax.naming.NameNotFoundException;
052: import javax.naming.NamingException;
053:
054: import org.jboss.annotation.ejb.Clustered;
055: import org.jboss.annotation.ejb.PoolClass;
056: import org.jboss.aop.AspectManager;
057: import org.jboss.aop.ClassContainer;
058: import org.jboss.aop.MethodInfo;
059: import org.jboss.aop.advice.AspectDefinition;
060: import org.jboss.aop.advice.Interceptor;
061: import org.jboss.aop.advice.Scope;
062: import org.jboss.aop.annotation.AnnotationElement;
063: import org.jboss.aop.joinpoint.ConstructorInvocation;
064: import org.jboss.aop.util.MethodHashing;
065: import org.jboss.ejb3.entity.PersistenceUnitDeployment;
066: import org.jboss.ejb3.interceptor.InterceptorInfo;
067: import org.jboss.ejb3.interceptor.InterceptorInfoRepository;
068: import org.jboss.ejb3.interceptor.InterceptorInjector;
069: import org.jboss.ejb3.interceptor.LifecycleInterceptorHandler;
070: import org.jboss.ejb3.metamodel.AssemblyDescriptor;
071: import org.jboss.ejb3.metamodel.EnterpriseBean;
072: import org.jboss.ejb3.security.JaccHelper;
073: import org.jboss.ejb3.statistics.InvocationStatistics;
074: import org.jboss.ejb3.tx.UserTransactionImpl;
075: import org.jboss.injection.DependsHandler;
076: import org.jboss.injection.EJBHandler;
077: import org.jboss.injection.EncInjector;
078: import org.jboss.injection.InjectionContainer;
079: import org.jboss.injection.InjectionHandler;
080: import org.jboss.injection.InjectionUtil;
081: import org.jboss.injection.Injector;
082: import org.jboss.injection.JndiInjectHandler;
083: import org.jboss.injection.PersistenceContextHandler;
084: import org.jboss.injection.PersistenceUnitHandler;
085: import org.jboss.injection.ResourceHandler;
086: import org.jboss.injection.WebServiceRefHandler;
087: import org.jboss.logging.Logger;
088: import org.jboss.metamodel.descriptor.EnvironmentRefGroup;
089: import org.jboss.naming.Util; //import org.jboss.virtual.VirtualFile;
090: import org.jboss.util.StringPropertyReplacer;
091:
092: /**
093: * Comment
094: *
095: * @author <a href="mailto:bill@jboss.org">Bill Burke</a>
096: * @version $Revision: 62705 $
097: */
098: public abstract class EJBContainer extends ClassContainer implements
099: Container, InjectionContainer {
100:
101: private static final Logger log = Logger
102: .getLogger(EJBContainer.class);
103:
104: // protected EjbEncFactory encFactory = new DefaultEjbEncFactory();
105:
106: protected Pool pool;
107:
108: protected String ejbName;
109:
110: protected ObjectName objectName;
111:
112: protected int defaultConstructorIndex;
113:
114: protected String beanClassName;
115:
116: protected ClassLoader classloader;
117:
118: // for performance there is an array.
119: protected List<Injector> injectors = new ArrayList<Injector>();
120:
121: protected Context enc;
122:
123: protected Class beanContextClass;
124:
125: //protected SessionCallbackHandler callbackHandler;
126: protected LifecycleInterceptorHandler callbackHandler;
127:
128: protected Hashtable initialContextProperties;
129:
130: protected Map<String, EncInjector> encInjectors = new HashMap<String, EncInjector>();
131:
132: protected EnterpriseBean xml;
133: protected AssemblyDescriptor assembly;
134:
135: protected Map<String, Map<AccessibleObject, Injector>> encInjections = new HashMap<String, Map<AccessibleObject, Injector>>();
136:
137: protected InterceptorInfoRepository interceptorRepository;
138:
139: protected List<InterceptorInfo> classInterceptors = new ArrayList<InterceptorInfo>();
140:
141: protected LinkedHashSet<InterceptorInfo> applicableInterceptors;
142:
143: private HashMap<Class, InterceptorInjector> interceptorInjectors = new HashMap<Class, InterceptorInjector>();
144:
145: private Ejb3Deployment deployment;
146:
147: private DependencyPolicy dependencyPolicy;
148:
149: private String jaccContextId;
150:
151: protected HashMap invokedMethod = new HashMap();
152:
153: protected InvocationStatistics invokeStats = new InvocationStatistics();
154:
155: private String partitionName;
156:
157: /**
158: * @param name Advisor name
159: * @param manager Domain to get interceptor bindings from
160: * @param cl the EJB's classloader
161: * @param beanClassName
162: * @param ejbName
163: * @param ctxProperties
164: * @param interceptorRepository
165: * @param deployment
166: */
167:
168: public EJBContainer(String name, AspectManager manager,
169: ClassLoader cl, String beanClassName, String ejbName,
170: Hashtable ctxProperties,
171: InterceptorInfoRepository interceptorRepository,
172: Ejb3Deployment deployment) {
173: super (name, manager);
174: this .deployment = deployment;
175: this .beanClassName = beanClassName;
176: this .classloader = cl;
177:
178: super .setChainOverridingForInheritedMethods(true);
179:
180: try {
181: clazz = classloader.loadClass(beanClassName);
182: } catch (ClassNotFoundException e) {
183: throw new RuntimeException(e);
184: }
185: this .ejbName = ejbName;
186: String on = Ejb3Module.BASE_EJB3_JMX_NAME + ","
187: + getDeploymentQualifiedName();
188: try {
189: objectName = new ObjectName(on);
190: } catch (MalformedObjectNameException e) {
191: throw new RuntimeException(
192: "failed to create object name for: " + on, e);
193: }
194: initialContextProperties = ctxProperties;
195: // Setting up enc the old (AS 4.2) way
196: Context ctx = getInitialContext();
197: try {
198: enc = ThreadLocalENCFactory.create(ctx);
199: Util.createSubcontext(enc, "env");
200: } catch (Exception e) {
201: throw new RuntimeException(e);
202: }
203: this .interceptorRepository = interceptorRepository;
204: this .interceptorRepository.addBeanClass(clazz.getName());
205: }
206:
207: // public EjbEncFactory getEncFactory()
208: // {
209: // return encFactory;
210: // }
211: //
212: // public void setEncFactory(EjbEncFactory encFactory)
213: // {
214: // this.encFactory = encFactory;
215: // }
216:
217: /**
218: * Makes sure that EJB's ENC is available
219: * Delegates to whatever implementation is used to push the ENC of the EJB
220: * onto the stack
221: *
222: */
223: public void pushEnc() {
224: ThreadLocalENCFactory.push(enc);
225: // encFactory.pushEnc(this);
226: }
227:
228: /**
229: * Pops EJB's ENC from the stack. Delegates to whatever implementation
230: * is used to pop the EJB's ENC from the stock
231: *
232: */
233: public void popEnc() {
234: ThreadLocalENCFactory.pop();
235: // encFactory.popEnc(this);
236: }
237:
238: public EnvironmentRefGroup getEnvironmentRefGroup() {
239: return xml;
240: }
241:
242: public List<Injector> getInjectors() {
243: return injectors;
244: }
245:
246: public String getJaccContextId() {
247: return jaccContextId;
248: }
249:
250: public void setJaccContextId(String jaccContextId) {
251: this .jaccContextId = jaccContextId;
252: }
253:
254: // public VirtualFile getRootFile()
255: // {
256: // return getDeploymentUnit().getRootFile();
257: // }
258:
259: /**
260: * Returns a String identifier for this bean that is qualified by the
261: * deployment, and hence should be unique across deployments. Name is of the
262: * form "ear=foo.ear,jar=foo.jar,name=Bar", where "Bar" is the value
263: * returned by {@link #getEjbName()}. The "ear=foo.ear" portion is ommitted
264: * if the bean is not packaged in an ear.
265: */
266: public String getDeploymentQualifiedName() {
267: DeploymentScope ear = deployment.getEar();
268: DeploymentUnit unit = deployment.getDeploymentUnit();
269: StringBuilder sb = new StringBuilder();
270: if (ear != null) {
271: sb.append("ear=");
272: sb.append(ear.getShortName());
273: sb.append(",");
274: }
275: sb.append("jar=");
276: sb.append(unit.getShortName());
277: sb.append(",name=");
278: sb.append(getEjbName());
279: return sb.toString();
280: }
281:
282: public DeploymentUnit getDeploymentUnit() {
283: return deployment.getDeploymentUnit();
284: }
285:
286: public Ejb3Deployment getDeployment() {
287: return deployment;
288: }
289:
290: public DependencyPolicy getDependencyPolicy() {
291: return dependencyPolicy;
292: }
293:
294: /**
295: * EJBContainer has finished with all metadata initialization from XML files and such.
296: * this is really a hook to do some processing after XML has been set up and before
297: * and processing of dependencies and such.
298: */
299: public void instantiated() {
300:
301: }
302:
303: /**
304: * introspects EJB container to find all dependencies
305: * and initialize any extra metadata.
306: * <p/>
307: * This must be called before container is registered with any microcontainer
308: *
309: * @param dependencyPolicy
310: */
311: public void processMetadata(DependencyPolicy dependencyPolicy) {
312: this .dependencyPolicy = dependencyPolicy;
313: // XML must be done first so that any annotation overrides are initialized
314:
315: // todo injection handlers should be pluggable from XML
316: Collection<InjectionHandler> handlers = new ArrayList<InjectionHandler>();
317: handlers.add(new EJBHandler());
318: handlers.add(new DependsHandler());
319: handlers.add(new JndiInjectHandler());
320: handlers.add(new PersistenceContextHandler());
321: handlers.add(new PersistenceUnitHandler());
322: handlers.add(new ResourceHandler());
323: handlers.add(new WebServiceRefHandler());
324:
325: ClassLoader old = Thread.currentThread()
326: .getContextClassLoader();
327: Thread.currentThread().setContextClassLoader(classloader);
328: try {
329: // EJB container's XML must be processed before interceptor's as it may override interceptor's references
330: for (InjectionHandler handler : handlers)
331: handler.loadXml(xml, this );
332:
333: Map<AccessibleObject, Injector> tmp = InjectionUtil
334: .processAnnotations(this , handlers, getBeanClass());
335: injectors.addAll(tmp.values());
336:
337: initialiseInterceptors();
338: for (InterceptorInfo interceptorInfo : applicableInterceptors) {
339: for (InjectionHandler handler : handlers) {
340: handler.loadXml(interceptorInfo.getXml(), this );
341: }
342: }
343: for (InterceptorInfo interceptorInfo : applicableInterceptors) {
344: Map<AccessibleObject, Injector> tmpInterceptor = InjectionUtil
345: .processAnnotations(this , handlers,
346: interceptorInfo.getClazz());
347: InterceptorInjector injector = new InterceptorInjector(
348: this , interceptorInfo, tmpInterceptor);
349: interceptorInjectors.put(interceptorInfo.getClazz(),
350: injector);
351: }
352: } finally {
353: Thread.currentThread().setContextClassLoader(old);
354: }
355: }
356:
357: public EnterpriseBean getXml() {
358: return xml;
359: }
360:
361: public void setXml(EnterpriseBean xml) {
362: this .xml = xml;
363: }
364:
365: public AssemblyDescriptor getAssemblyDescriptor() {
366: return assembly;
367: }
368:
369: public void setAssemblyDescriptor(AssemblyDescriptor assembly) {
370: this .assembly = assembly;
371: }
372:
373: public InterceptorInfoRepository getInterceptorRepository() {
374: return interceptorRepository;
375: }
376:
377: public List<InterceptorInfo> getClassInterceptors() {
378: initialiseInterceptors();
379: return classInterceptors;
380: }
381:
382: public HashSet<InterceptorInfo> getApplicableInterceptors() {
383: initialiseInterceptors();
384: return applicableInterceptors;
385: }
386:
387: public HashMap<Class, InterceptorInjector> getInterceptorInjectors() {
388: initialiseInterceptors();
389: return interceptorInjectors;
390: }
391:
392: public Map<String, EncInjector> getEncInjectors() {
393: return encInjectors;
394: }
395:
396: public ClassLoader getClassloader() {
397: return classloader;
398: }
399:
400: public InitialContext getInitialContext() {
401: try {
402: if (initialContextProperties == null)
403: return new InitialContext();
404: else
405: return new InitialContext(initialContextProperties);
406: } catch (NamingException e) {
407: throw new RuntimeException(e);
408: }
409: }
410:
411: public Map<String, Map<AccessibleObject, Injector>> getEncInjections() {
412: return encInjections;
413: }
414:
415: public Context getEnc() {
416: // if (enc == null)
417: // {
418: // enc = encFactory.getEnc(this);
419: // }
420: return enc;
421: }
422:
423: public Hashtable getInitialContextProperties() {
424: return initialContextProperties;
425: }
426:
427: public ObjectName getObjectName() {
428: return objectName;
429: }
430:
431: public String getEjbName() {
432: return ejbName;
433: }
434:
435: public String getBeanClassName() {
436: return beanClassName;
437: }
438:
439: public Class getBeanClass() {
440: return clazz;
441: }
442:
443: public Pool getPool() {
444: return pool;
445: }
446:
447: /**
448: * Gets the name of the cluster partition with which this container is
449: * associated. Not available until <code>EJBContainer.start()</code>
450: * is completed.
451: *
452: * @return the name of the cluster partition with which this container is
453: * associated, or <code>null</code> if the container is not clustered
454: */
455: public String getPartitionName() {
456: return partitionName;
457: }
458:
459: public Object construct() {
460: Interceptor[] cInterceptors = constructorInterceptors[defaultConstructorIndex];
461: if (cInterceptors == null) {
462: try {
463: return constructors[defaultConstructorIndex]
464: .newInstance();
465: } catch (InstantiationException e) {
466: throw new RuntimeException(e);
467: } catch (IllegalAccessException e) {
468: throw new RuntimeException(e);
469: } catch (InvocationTargetException e) {
470: throw new RuntimeException(e);
471: }
472: }
473: ConstructorInvocation invocation = new ConstructorInvocation(
474: cInterceptors);
475:
476: invocation.setAdvisor(this );
477: invocation
478: .setConstructor(constructors[defaultConstructorIndex]);
479: try {
480: return invocation.invokeNext();
481: } catch (Throwable throwable) {
482: throw new RuntimeException(throwable);
483: }
484:
485: }
486:
487: public void create() throws Exception {
488: // EJBTHREE-655: we need an instance after create
489: initializeClassContainer();
490: for (int i = 0; i < constructors.length; i++) {
491: if (constructors[i].getParameterTypes().length == 0) {
492: defaultConstructorIndex = i;
493: break;
494: }
495: }
496: }
497:
498: // Everything must be done in start to make sure all dependencies have been satisfied
499: public void start() throws Exception {
500: initializePool();
501:
502: for (EncInjector injector : encInjectors.values()) {
503: injector.inject(this );
504: }
505:
506: // creating of injector array should come after injection into ENC as an ENC injector
507: // may add additional injectors into the injector list. An example is an extended persistence
508: // context which mush be created and added to the SFSB bean context.
509:
510: Injector[] injectors2 = injectors
511: .toArray(new Injector[injectors.size()]);
512: if (pool != null)
513: pool.setInjectors(injectors2);
514:
515: createCallbackHandler();
516:
517: JaccHelper.configureContainer(jaccContextId, this );
518:
519: // If we're clustered, find our partition name
520: findPartitionName();
521:
522: log.info("STARTED EJB: " + clazz.getName() + " ejbName: "
523: + ejbName);
524: }
525:
526: public void stop() throws Exception {
527: // encFactory.cleanupEnc(this);
528:
529: if (pool != null) {
530: pool.destroy();
531: pool = null;
532: }
533:
534: log.info("STOPPED EJB: " + clazz.getName() + " ejbName: "
535: + ejbName);
536: }
537:
538: public void destroy() throws Exception {
539: super .cleanup();
540: }
541:
542: protected void initializePool() throws Exception {
543: PoolClass poolClass = (PoolClass) resolveAnnotation(PoolClass.class);
544: Class<? extends Pool> poolClazz = poolClass.value();
545: int maxSize = poolClass.maxSize();
546: long timeout = poolClass.timeout();
547: pool = poolClazz.newInstance();
548: pool
549: .initialize(this , beanContextClass, clazz, maxSize,
550: timeout);
551:
552: resolveInjectors();
553: pool.setInjectors(injectors.toArray(new Injector[injectors
554: .size()]));
555: }
556:
557: public void invokePostConstruct(BeanContext beanContext) {
558: callbackHandler.postConstruct(beanContext);
559: }
560:
561: public void invokePreDestroy(BeanContext beanContext) {
562: callbackHandler.preDestroy(beanContext);
563: }
564:
565: public void invokePostActivate(BeanContext beanContext) {
566: throw new RuntimeException(
567: "PostActivate not implemented for container");
568: }
569:
570: public void invokePrePassivate(BeanContext beanContext) {
571: throw new RuntimeException(
572: "PrePassivate not implemented for container");
573: }
574:
575: public void invokeInit(Object bean) {
576:
577: }
578:
579: public void invokeInit(Object bean, Class[] initParameterTypes,
580: Object[] initParameterValues) {
581:
582: }
583:
584: public static final String MANAGED_ENTITY_MANAGER_FACTORY = "ManagedEntityManagerFactory";
585:
586: public static final String ENTITY_MANAGER_FACTORY = "EntityManagerFactory";
587:
588: protected void resolveInjectors() throws Exception {
589: pushEnc();
590: try {
591: Thread.currentThread().setContextClassLoader(classloader);
592: try {
593: Util.rebind(getEnc(), "UserTransaction",
594: new UserTransactionImpl());
595: } catch (NamingException e) {
596: NamingException namingException = new NamingException(
597: "Could not bind user transaction for ejb name "
598: + ejbName
599: + " into JNDI under jndiName: "
600: + getEnc().getNameInNamespace() + "/"
601: + "UserTransaction");
602: namingException.setRootCause(e);
603: throw namingException;
604: }
605: } finally {
606: popEnc();
607: }
608: }
609:
610: protected void createCallbackHandler() {
611: try {
612: callbackHandler = new LifecycleInterceptorHandler(this ,
613: getHandledCallbacks());
614: } catch (Exception e) {
615: throw new RuntimeException(
616: "Error creating callback handler for bean "
617: + beanClassName, e);
618: }
619: }
620:
621: protected Class[] getHandledCallbacks() {
622: return new Class[] { PostConstruct.class, PreDestroy.class,
623: Timeout.class };
624: }
625:
626: private void initialiseInterceptors() {
627: if (applicableInterceptors == null) {
628: log.debug("Initialising interceptors for " + getEjbName()
629: + "...");
630: HashSet<InterceptorInfo> defaultInterceptors = interceptorRepository
631: .getDefaultInterceptors();
632: log.debug("Default interceptors: " + defaultInterceptors);
633:
634: classInterceptors = interceptorRepository
635: .getClassInterceptors(this );
636: log.debug("Class interceptors: " + classInterceptors);
637:
638: applicableInterceptors = new LinkedHashSet<InterceptorInfo>();
639: if (defaultInterceptors != null)
640: applicableInterceptors.addAll(defaultInterceptors);
641: if (classInterceptors != null)
642: applicableInterceptors.addAll(classInterceptors);
643:
644: Method[] methods = clazz.getMethods();
645: for (int i = 0; i < methods.length; i++) {
646: List methodIcptrs = interceptorRepository
647: .getMethodInterceptors(this , methods[i]);
648: if (methodIcptrs != null && methodIcptrs.size() > 0) {
649: log.debug("Method interceptors for " + methods[i]
650: + ": " + methodIcptrs);
651: applicableInterceptors.addAll(methodIcptrs);
652: }
653: }
654: log.debug("All applicable interceptor classes: "
655: + applicableInterceptors);
656: }
657: }
658:
659: protected void findPartitionName() {
660: Clustered clustered = (Clustered) resolveAnnotation(Clustered.class);
661: if (clustered == null) {
662: partitionName = null;
663: return;
664: }
665:
666: String value = clustered.partition();
667: try {
668: String replacedValue = StringPropertyReplacer
669: .replaceProperties(value);
670: if (value != replacedValue) {
671: log.debug("Replacing @Clustered partition attribute "
672: + value + " with " + replacedValue);
673: value = replacedValue;
674: }
675: } catch (Exception e) {
676: log
677: .warn("Unable to replace @Clustered partition attribute "
678: + value
679: + ". Caused by "
680: + e.getClass()
681: + " " + e.getMessage());
682: }
683:
684: partitionName = value;
685: }
686:
687: public Object getBusinessObject(BeanContext beanContext,
688: Class businessObject) throws IllegalStateException {
689: throw new IllegalStateException("Not implemented");
690: }
691:
692: public Object getInvokedBusinessInterface(BeanContext beanContext)
693: throws IllegalStateException {
694: throw new IllegalStateException("Not implemented");
695: }
696:
697: protected Object getInvokedInterface(Method method) {
698: Remote remoteAnnotation = (Remote) resolveAnnotation(Remote.class);
699: if (remoteAnnotation != null) {
700: Class[] remotes = remoteAnnotation.value();
701: for (int i = 0; i < remotes.length; ++i) {
702: try {
703: remotes[i].getMethod(method.getName(), method
704: .getParameterTypes());
705: return remotes[i];
706: } catch (NoSuchMethodException e) {
707: }
708: }
709: }
710:
711: Local localAnnotation = (Local) resolveAnnotation(Local.class);
712: if (localAnnotation != null) {
713: Class[] locals = localAnnotation.value();
714: for (int i = 0; i < locals.length; ++i) {
715: Method[] interfaceMethods = locals[i].getMethods();
716: for (int j = 0; j < interfaceMethods.length; ++j) {
717: if (interfaceMethods[j].equals(method))
718: return locals[i];
719: }
720: }
721: }
722:
723: return null;
724: }
725:
726: // todo these method overrides for aop are for performance reasons
727: private Class loadPublicAnnotation(String annotation) {
728: try {
729: Class ann = classloader.loadClass(annotation);
730: if (!ann.isAnnotation())
731: return null;
732: Retention retention = (Retention) ann
733: .getAnnotation(Retention.class);
734: if (retention != null
735: && retention.value() == RetentionPolicy.RUNTIME)
736: return ann;
737:
738: } catch (ClassNotFoundException ignored) {
739: }
740: return null;
741: }
742:
743: @Override
744: public boolean hasAnnotation(Class tgt, String annotation) {
745: if (annotations.hasClassAnnotation(annotation))
746: return true;
747: if (tgt == null)
748: return false;
749: try {
750: Class ann = loadPublicAnnotation(annotation);
751: // it is metadata or CLASS annotation
752: if (ann == null)
753: return AnnotationElement.isAnyAnnotationPresent(tgt,
754: annotation);
755: return tgt.isAnnotationPresent(ann);
756: } catch (Exception e) {
757: throw new RuntimeException(e); //To change body of catch statement use Options | File Templates.
758: }
759: }
760:
761: @Override
762: public boolean hasAnnotation(Method m, String annotation) {
763: if (annotations.hasAnnotation(m, annotation))
764: return true;
765: try {
766: Class ann = loadPublicAnnotation(annotation);
767: // it is metadata or CLASS annotation
768: if (ann == null)
769: return AnnotationElement.isAnyAnnotationPresent(m,
770: annotation);
771: return m.isAnnotationPresent(ann);
772: } catch (Exception e) {
773: throw new RuntimeException(e); //To change body of catch statement use Options | File Templates.
774: }
775: }
776:
777: @Override
778: public boolean hasAnnotation(Field m, String annotation) {
779: if (annotations.hasAnnotation(m, annotation))
780: return true;
781: try {
782: Class ann = loadPublicAnnotation(annotation);
783: // it is metadata or CLASS annotation
784: if (ann == null)
785: return AnnotationElement.isAnyAnnotationPresent(m,
786: annotation);
787: return m.isAnnotationPresent(ann);
788: } catch (Exception e) {
789: throw new RuntimeException(e); //To change body of catch statement use Options | File Templates.
790: }
791: }
792:
793: @Override
794: public boolean hasAnnotation(Constructor m, String annotation) {
795: if (annotations.hasAnnotation(m, annotation))
796: return true;
797: try {
798: Class ann = loadPublicAnnotation(annotation);
799: // it is metadata or CLASS annotation
800: if (ann == null)
801: return AnnotationElement.isAnyAnnotationPresent(m,
802: annotation);
803: return m.isAnnotationPresent(ann);
804: } catch (Exception e) {
805: throw new RuntimeException(e); //To change body of catch statement use Options | File Templates.
806: }
807: }
808:
809: public Container resolveEjbContainer(String link, Class businessIntf) {
810: return deployment.getEjbContainer(link, businessIntf);
811: }
812:
813: public Container resolveEjbContainer(Class businessIntf)
814: throws NameNotFoundException {
815: return deployment.getEjbContainer(businessIntf);
816: }
817:
818: public <T extends Annotation> T getAnnotation(
819: Class<T> annotationType, Class<?> clazz) {
820: if (clazz == this .getBeanClass()) {
821: return (T) resolveAnnotation(annotationType);
822: }
823: return clazz.getAnnotation(annotationType);
824: }
825:
826: public <T extends Annotation> T getAnnotation(
827: Class<T> annotationType, Class<?> clazz, Method method) {
828: if (clazz == this .getBeanClass()) {
829: return (T) resolveAnnotation(method, annotationType);
830: }
831: return method.getAnnotation(annotationType);
832: }
833:
834: public <T extends Annotation> T getAnnotation(
835: Class<T> annotationType, Method method) {
836: return (T) resolveAnnotation(method, annotationType);
837: }
838:
839: public <T extends Annotation> T getAnnotation(
840: Class<T> annotationType, Class<?> clazz, Field field) {
841: if (clazz == this .getBeanClass()) {
842: return (T) resolveAnnotation(field, annotationType);
843: }
844: return field.getAnnotation(annotationType);
845: }
846:
847: public <T extends Annotation> T getAnnotation(
848: Class<T> annotationType, Field field) {
849: return (T) resolveAnnotation(field, annotationType);
850: }
851:
852: @Override
853: public Object resolveAnnotation(Method m, Class annotation) {
854: Object value = super .resolveAnnotation(m, annotation);
855: if (value == null && m.isBridge())
856: value = getBridgedAnnotation(m, annotation);
857: return value;
858: }
859:
860: protected Object getBridgedAnnotation(Method bridgeMethod,
861: Class annotation) {
862: Method[] methods = bridgeMethod.getDeclaringClass()
863: .getMethods();
864: int i = 0;
865: boolean found = false;
866: Class[] bridgeParams = bridgeMethod.getParameterTypes();
867: while (i < methods.length && !found) {
868: if (!methods[i].isBridge()
869: && methods[i].getName().equals(
870: bridgeMethod.getName())) {
871: Class[] params = methods[i].getParameterTypes();
872: if (params.length == bridgeParams.length) {
873: int j = 0;
874: boolean matches = true;
875: while (j < params.length && matches) {
876: if (!bridgeParams[j]
877: .isAssignableFrom(params[j]))
878: matches = false;
879: ++j;
880: }
881:
882: if (matches)
883: return resolveAnnotation(methods[i], annotation);
884: }
885: }
886: ++i;
887: }
888:
889: return null;
890: }
891:
892: public Object resolveAnnotation(Method m, Class[] annotationChoices) {
893: Object value = null;
894: int i = 0;
895: while (value == null && i < annotationChoices.length) {
896: value = resolveAnnotation(m, annotationChoices[i++]);
897: }
898:
899: return value;
900: }
901:
902: public String getIdentifier() {
903: return getEjbName();
904: }
905:
906: public String getDeploymentDescriptorType() {
907: return "ejb-jar.xml";
908: }
909:
910: public PersistenceUnitDeployment getPersistenceUnitDeployment(
911: String unitName) throws NameNotFoundException {
912: return deployment.getPersistenceUnitDeployment(unitName);
913: }
914:
915: public String getEjbJndiName(Class businessInterface)
916: throws NameNotFoundException {
917: return deployment.getEjbJndiName(businessInterface);
918: }
919:
920: public String getEjbJndiName(String link, Class businessInterface) {
921: return deployment.getEjbJndiName(link, businessInterface);
922: }
923:
924: public InvocationStatistics getInvokeStats() {
925: return invokeStats;
926: }
927:
928: public MethodInfo getMethodInfo(Method method) {
929: long hash = MethodHashing.calculateHash(method);
930: MethodInfo info = (MethodInfo) methodInterceptors.get(hash);
931: if (info == null) {
932: throw new RuntimeException(
933: "Could not resolve beanClass method from proxy call: "
934: + method.toString());
935: }
936: return info;
937: }
938: }
|