0001: /**
0002: * EasyBeans
0003: * Copyright (C) 2006 Bull S.A.S.
0004: * Contact: easybeans@ow2.org
0005: *
0006: * This library is free software; you can redistribute it and/or
0007: * modify it under the terms of the GNU Lesser General Public
0008: * License as published by the Free Software Foundation; either
0009: * version 2.1 of the License, or any later version.
0010: *
0011: * This library is distributed in the hope that it will be useful,
0012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0014: * Lesser General Public License for more details.
0015: *
0016: * You should have received a copy of the GNU Lesser General Public
0017: * License along with this library; if not, write to the Free Software
0018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
0019: * USA
0020: *
0021: * --------------------------------------------------------------------------
0022: * $Id: MetadataMerge.java 2057 2007-11-21 15:35:32Z benoitf $
0023: * --------------------------------------------------------------------------
0024: */package org.ow2.easybeans.deployment.xml.helper;
0025:
0026: import static org.ow2.easybeans.deployment.xml.struct.common.LifeCycleCallback.POST_ACTIVATE;
0027: import static org.ow2.easybeans.deployment.xml.struct.common.LifeCycleCallback.POST_CONSTRUCT;
0028: import static org.ow2.easybeans.deployment.xml.struct.common.LifeCycleCallback.PRE_DESTROY;
0029: import static org.ow2.easybeans.deployment.xml.struct.common.LifeCycleCallback.PRE_PASSIVATE;
0030:
0031: import java.util.ArrayList;
0032: import java.util.List;
0033:
0034: import javax.ejb.Remove;
0035: import javax.ejb.TransactionAttributeType;
0036: import javax.ejb.TransactionManagementType;
0037:
0038: import org.ow2.easybeans.asm.Type;
0039: import org.ow2.easybeans.deployment.annotations.ClassType;
0040: import org.ow2.easybeans.deployment.annotations.TransactionAttributeLevel;
0041: import org.ow2.easybeans.deployment.annotations.impl.JActivationConfigProperty;
0042: import org.ow2.easybeans.deployment.annotations.impl.JAnnotationResource;
0043: import org.ow2.easybeans.deployment.annotations.impl.JApplicationException;
0044: import org.ow2.easybeans.deployment.annotations.impl.JCommonBean;
0045: import org.ow2.easybeans.deployment.annotations.impl.JEjbEJB;
0046: import org.ow2.easybeans.deployment.annotations.impl.JInterceptors;
0047: import org.ow2.easybeans.deployment.annotations.impl.JLocal;
0048: import org.ow2.easybeans.deployment.annotations.impl.JMessageDriven;
0049: import org.ow2.easybeans.deployment.annotations.impl.JRemote;
0050: import org.ow2.easybeans.deployment.annotations.impl.JRemove;
0051: import org.ow2.easybeans.deployment.annotations.metadata.ClassAnnotationMetadata;
0052: import org.ow2.easybeans.deployment.annotations.metadata.CommonAnnotationMetadata;
0053: import org.ow2.easybeans.deployment.annotations.metadata.EjbJarAnnotationMetadata;
0054: import org.ow2.easybeans.deployment.annotations.metadata.FieldAnnotationMetadata;
0055: import org.ow2.easybeans.deployment.annotations.metadata.MethodAnnotationMetadata;
0056: import org.ow2.easybeans.deployment.xml.struct.AbsBean;
0057: import org.ow2.easybeans.deployment.xml.struct.AssemblyDescriptor;
0058: import org.ow2.easybeans.deployment.xml.struct.ContainerTransaction;
0059: import org.ow2.easybeans.deployment.xml.struct.EJB3;
0060: import org.ow2.easybeans.deployment.xml.struct.EnterpriseBeans;
0061: import org.ow2.easybeans.deployment.xml.struct.Interceptor;
0062: import org.ow2.easybeans.deployment.xml.struct.InterceptorBinding;
0063: import org.ow2.easybeans.deployment.xml.struct.Interceptors;
0064: import org.ow2.easybeans.deployment.xml.struct.MessageDriven;
0065: import org.ow2.easybeans.deployment.xml.struct.MethodPermission;
0066: import org.ow2.easybeans.deployment.xml.struct.RemoveMethod;
0067: import org.ow2.easybeans.deployment.xml.struct.Session;
0068: import org.ow2.easybeans.deployment.xml.struct.common.AbsEJBRef;
0069: import org.ow2.easybeans.deployment.xml.struct.common.AbsEnvironment;
0070: import org.ow2.easybeans.deployment.xml.struct.common.ActivationConfig;
0071: import org.ow2.easybeans.deployment.xml.struct.common.AroundInvoke;
0072: import org.ow2.easybeans.deployment.xml.struct.common.EJBLocalRef;
0073: import org.ow2.easybeans.deployment.xml.struct.common.EJBRef;
0074: import org.ow2.easybeans.deployment.xml.struct.common.InjectionTarget;
0075: import org.ow2.easybeans.deployment.xml.struct.common.LifeCycleCallback;
0076: import org.ow2.easybeans.deployment.xml.struct.common.MessageDestinationRef;
0077: import org.ow2.easybeans.deployment.xml.struct.common.MethodDD;
0078: import org.ow2.easybeans.deployment.xml.struct.common.ResourceEnvRef;
0079: import org.ow2.easybeans.deployment.xml.struct.common.ResourceRef;
0080: import org.ow2.util.log.Log;
0081: import org.ow2.util.log.LogFactory;
0082:
0083: /**
0084: * This class merge the information of the struct representing EJB DD into the
0085: * metadata.
0086: * @author Florent Benoit
0087: */
0088: public final class MetadataMerge {
0089:
0090: /**
0091: * Wildcard attribute.
0092: */
0093: private static final String WILDCARD = "*";
0094:
0095: /**
0096: * Defines java.lang.Object class.
0097: */
0098: public static final String JAVA_LANG_OBJECT = "java/lang/Object";
0099:
0100: /**
0101: * Metadata for an ejb-jar.
0102: */
0103: private EjbJarAnnotationMetadata ejbMetadata = null;
0104:
0105: /**
0106: * Logger.
0107: */
0108: private static Log logger = LogFactory.getLog(MetadataMerge.class);
0109:
0110: /**
0111: * Helper class, no public constructor.
0112: * @param ejbMetadata the metadata corresponding to an EJB-JAR file.
0113: */
0114: private MetadataMerge(final EjbJarAnnotationMetadata ejbMetadata) {
0115: this .ejbMetadata = ejbMetadata;
0116: }
0117:
0118: /**
0119: * Takes struct of metadata and adds/set information on class/methods
0120: * metadata.
0121: * @param ejbMetadata the metadata corresponding to an EJB-JAR file.
0122: */
0123: public static void merge(final EjbJarAnnotationMetadata ejbMetadata) {
0124: new MetadataMerge(ejbMetadata).resolve();
0125: }
0126:
0127: /**
0128: * Do all merging operations.
0129: */
0130: private void resolve() {
0131:
0132: EJB3 ejb3 = ejbMetadata.getEjb3();
0133: if (ejb3 != null) {
0134: // Get enterprise beans
0135: EnterpriseBeans enterpriseBeans = ejb3.getEnterpriseBeans();
0136: if (enterpriseBeans != null) {
0137:
0138: // get session beans
0139: List<Session> sessionList = enterpriseBeans
0140: .getSessionList();
0141: for (Session session : sessionList) {
0142: // get ejb-name
0143: String ejbName = session.getEjbName();
0144: String ejbClass = session.getEjbClass();
0145: ClassAnnotationMetadata classAnnotationMetadata = findClassForEjb(
0146: ejbName, ejbClass);
0147:
0148: // class is found, then apply all customization.
0149: applySessionBean(session, classAnnotationMetadata);
0150: }
0151:
0152: // MDB
0153: List<MessageDriven> messageDrivenList = enterpriseBeans
0154: .getMessageDrivenList();
0155: for (MessageDriven messageDriven : messageDrivenList) {
0156: // get ejb-name
0157: String ejbName = messageDriven.getEjbName();
0158: String ejbClass = messageDriven.getEjbClass();
0159: ClassAnnotationMetadata classAnnotationMetadata = findClassForEjb(
0160: ejbName, ejbClass);
0161:
0162: // class is found, then apply all customization.
0163: applyMessageDrivenBean(messageDriven,
0164: classAnnotationMetadata);
0165: }
0166:
0167: }
0168:
0169: // Interceptors
0170: Interceptors interceptors = ejb3.getInterceptors();
0171: if (interceptors != null) {
0172: applyInterceptors(interceptors);
0173: }
0174:
0175: // Assembly descriptor
0176: AssemblyDescriptor assemblyDescriptor = ejb3
0177: .getAssemblyDescriptor();
0178: if (assemblyDescriptor != null) {
0179:
0180: // merge application-exception
0181: mergeApplicationException(assemblyDescriptor);
0182:
0183: // merge interceptor-binding
0184: mergeInterceptorBinding(assemblyDescriptor);
0185:
0186: // merge container-transaction
0187: mergeContainerTransaction(assemblyDescriptor);
0188:
0189: // merge security
0190: mergeAssemblySecurity(assemblyDescriptor);
0191:
0192: }
0193: }
0194: }
0195:
0196: /**
0197: * Apply rules for the interceptors defined in the XML DD.
0198: * @param interceptors the interceptors struct representing
0199: * <interceptors> element
0200: */
0201: private void applyInterceptors(final Interceptors interceptors) {
0202: // Get interceptors
0203: List<Interceptor> interceptorList = interceptors
0204: .getInterceptorList();
0205: if (interceptorList != null) {
0206: for (Interceptor interceptor : interceptorList) {
0207:
0208: // Check that there is an interceptor class defined
0209: String itCptClass = interceptor.getInterceptorClass();
0210: if (itCptClass == null) {
0211: throw new IllegalStateException(
0212: "Invalid interceptor with name '"
0213: + interceptor
0214: + "': No interceptor-class");
0215: }
0216:
0217: // Class Metadata
0218: ClassAnnotationMetadata itcpMetadata = ejbMetadata
0219: .getClassAnnotationMetadata(encode(itCptClass));
0220: if (itcpMetadata == null) {
0221: throw new IllegalStateException(
0222: "No metadata found for class '"
0223: + itCptClass + "'.");
0224: }
0225:
0226: // Will use metadata of the interceptor class
0227: applyJndiEnvironmentRefsGroup(interceptor, itcpMetadata);
0228:
0229: }
0230: }
0231: }
0232:
0233: /**
0234: * Apply rules for a session bean.
0235: * @param sessionbean the struct (XML DD)
0236: * @param classAnnotationMetadata (Annotation metadata)
0237: */
0238: private void applySessionBean(final Session sessionbean,
0239: final ClassAnnotationMetadata classAnnotationMetadata) {
0240: applyCommonBean(sessionbean, classAnnotationMetadata);
0241:
0242: // set session-type
0243: String sessionType = sessionbean.getSessionType();
0244: if (sessionType == null && !classAnnotationMetadata.isSession()) {
0245: throw new IllegalStateException(
0246: "Missing session-type for bean '" + sessionbean
0247: + "' and no annotation in '"
0248: + classAnnotationMetadata + "'.");
0249: }
0250: // set the type of bean
0251: if ("Stateless".equals(sessionType)) {
0252: classAnnotationMetadata.setClassType(ClassType.STATELESS);
0253: } else if ("Stateful".equals(sessionType)) {
0254: classAnnotationMetadata.setClassType(ClassType.STATEFUL);
0255: }
0256:
0257: // Transaction type
0258: String transactionType = sessionbean.getTransactionType();
0259: if (transactionType != null) {
0260: if ("Bean".equals(transactionType)) {
0261: classAnnotationMetadata
0262: .setTransactionManagementType(TransactionManagementType.BEAN);
0263: } else if ("Container".equals(transactionType)) {
0264: classAnnotationMetadata
0265: .setTransactionManagementType(TransactionManagementType.CONTAINER);
0266: } else {
0267: throw new IllegalStateException(
0268: "Invalid transaction type '" + transactionType
0269: + "' found");
0270: }
0271: }
0272:
0273: // Remote Home
0274: String remoteHome = sessionbean.getRemoteHome();
0275: if (remoteHome != null) {
0276: classAnnotationMetadata.setRemoteHome(remoteHome);
0277: }
0278:
0279: // Local Home
0280: String localHome = sessionbean.getLocalHome();
0281: if (localHome != null) {
0282: classAnnotationMetadata.setLocalHome(localHome);
0283: }
0284:
0285: // local interface
0286: if (sessionbean.getBusinessLocalList().size() > 0) {
0287: JLocal jLocal = classAnnotationMetadata
0288: .getLocalInterfaces();
0289: if (jLocal == null) {
0290: jLocal = new JLocal();
0291: classAnnotationMetadata.setLocalInterfaces(jLocal);
0292: }
0293: for (String itf : sessionbean.getBusinessLocalList()) {
0294: String encodedItf = encode(itf);
0295: if (!jLocal.contains(encodedItf)) {
0296: jLocal.addInterface(encodedItf);
0297: }
0298: }
0299: }
0300:
0301: // Mapped name
0302: if (sessionbean.getMappedName() != null) {
0303: JCommonBean jCommonBean = classAnnotationMetadata
0304: .getJCommonBean();
0305: if (jCommonBean == null) {
0306: throw new IllegalStateException(
0307: "No JCommonBean attribute on class '"
0308: + classAnnotationMetadata
0309: .getClassName()
0310: + "' while there is a mapped name.");
0311: }
0312: jCommonBean.setMappedName(sessionbean.getMappedName());
0313: }
0314:
0315: // remote interface
0316: if (sessionbean.getBusinessRemoteList().size() > 0) {
0317: JRemote jRemote = classAnnotationMetadata
0318: .getRemoteInterfaces();
0319: if (jRemote == null) {
0320: jRemote = new JRemote();
0321: classAnnotationMetadata.setRemoteInterfaces(jRemote);
0322: }
0323: for (String itf : sessionbean.getBusinessRemoteList()) {
0324: String encodedItf = encode(itf);
0325: if (!jRemote.contains(encodedItf)) {
0326: jRemote.addInterface(encodedItf);
0327: }
0328: }
0329: }
0330:
0331: // Remove methods (for stateful bean)
0332: if (sessionbean.getRemoveMethodList().size() > 0) {
0333: if (!classAnnotationMetadata.isStateful()) {
0334: throw new IllegalStateException(
0335: "Cannot apply XML DD remove methods on a bean which is not a stateful bean. Bean class is '"
0336: + classAnnotationMetadata
0337: .getClassName()
0338: + "'. Remove Methods are '"
0339: + sessionbean.getRemoveMethodList()
0340: + "'.");
0341: }
0342:
0343: for (RemoveMethod removeMethod : sessionbean
0344: .getRemoveMethodList()) {
0345: MethodDD method = removeMethod.getMethod();
0346:
0347: // method case
0348: List<MethodAnnotationMetadata> methods = getMethodsForGivenMethodDD(
0349: method, classAnnotationMetadata);
0350: // No method found (warning)
0351: if (methods.size() == 0) {
0352: logger
0353: .warn(
0354: "No method found for the remove-method ''{0}'' on the class ''{1}''",
0355: method, classAnnotationMetadata
0356: .getClassName());
0357: } else if (methods.size() > 1) {
0358: logger
0359: .warn(
0360: "Found more than 1 method for the remove-method ''{0}'' on the class ''{1}''."
0361: + "All these methods will be set as remove methods.",
0362: method, classAnnotationMetadata
0363: .getClassName());
0364: }
0365:
0366: // Set as a remove method
0367: for (MethodAnnotationMetadata methodAnnotationMetadata : methods) {
0368:
0369: // Get existing value
0370: Remove previousRemove = methodAnnotationMetadata
0371: .getJRemove();
0372:
0373: // Value of the XML (for retain)
0374: Boolean retainXML = removeMethod
0375: .getRetainIfException();
0376:
0377: // If value has been defined in the XML, use this value,
0378: // else use the value of the annotation, else the default
0379: // value (false)
0380: boolean retain = false;
0381: if (retainXML != null) {
0382: retain = retainXML.booleanValue();
0383: } else if (previousRemove != null) {
0384: // got value of the annotation
0385: retain = previousRemove.retainIfException();
0386: }
0387:
0388: // Set the new value
0389: JRemove jRemove = new JRemove(retain);
0390: methodAnnotationMetadata.setRemove(jRemove);
0391: }
0392: }
0393: }
0394: }
0395:
0396: /**
0397: * Apply rules for a Message Driven Bean.
0398: * @param messageDrivenBean the struct (XML DD)
0399: * @param classAnnotationMetadata (Annotation metadata)
0400: */
0401: private void applyMessageDrivenBean(
0402: final MessageDriven messageDrivenBean,
0403: final ClassAnnotationMetadata classAnnotationMetadata) {
0404: applyCommonBean(messageDrivenBean, classAnnotationMetadata);
0405:
0406: // TODO: messaging-type
0407: String messagingType = messageDrivenBean.getMessagingType();
0408:
0409: // Activation config
0410: List<ActivationConfig> activationConfigList = messageDrivenBean
0411: .getActivationConfigList();
0412: for (ActivationConfig activationConfig : activationConfigList) {
0413: JMessageDriven jMessageDriven = classAnnotationMetadata
0414: .getJMessageDriven();
0415: if (jMessageDriven == null) {
0416: jMessageDriven = new JMessageDriven();
0417: classAnnotationMetadata
0418: .setJMessageDriven(jMessageDriven);
0419: }
0420:
0421: JActivationConfigProperty actProperty = new JActivationConfigProperty(
0422: activationConfig.getName(), activationConfig
0423: .getValue());
0424: jMessageDriven.addActivationConfigProperty(actProperty);
0425: }
0426:
0427: }
0428:
0429: /**
0430: * Apply rules for a common bean.
0431: * @param bean the struct (XML DD)
0432: * @param classAnnotationMetadata (Annotation metadata)
0433: */
0434: private void applyCommonBean(final AbsBean bean,
0435: final ClassAnnotationMetadata classAnnotationMetadata) {
0436: // no Common bean, create one.
0437: if (classAnnotationMetadata.getJCommonBean() == null) {
0438: classAnnotationMetadata.setJCommonBean(new JCommonBean());
0439: }
0440: // Sets the ejb-name
0441: JCommonBean jCommonBean = classAnnotationMetadata
0442: .getJCommonBean();
0443: boolean isDefaultName = jCommonBean.isDefaultName();
0444: if (isDefaultName) {
0445: jCommonBean.setName(bean.getEjbName());
0446: jCommonBean.setDefaultName(false);
0447: } else {
0448: // Bean already registered with this name, add an alias
0449: jCommonBean.addAlias(bean.getEjbName());
0450: }
0451:
0452: // Mapped name
0453: if (bean.getMappedName() != null) {
0454: if (jCommonBean == null) {
0455: throw new IllegalStateException(
0456: "No JCommonBean attribute on class '"
0457: + classAnnotationMetadata
0458: .getClassName()
0459: + "' while there is a mapped name.");
0460: }
0461: jCommonBean.setMappedName(bean.getMappedName());
0462: }
0463:
0464: // Apply run-as role
0465: String runAsRole = bean.getRunAsRole();
0466: if (runAsRole != null) {
0467: classAnnotationMetadata.setRunAs(runAsRole);
0468: }
0469:
0470: applyJndiEnvironmentRefsGroup(bean, classAnnotationMetadata);
0471:
0472: }
0473:
0474: /**
0475: * Apply rules for a an environment.
0476: * @param envGroup the struct (XML DD)
0477: * @param classAnnotationMetadata (Annotation metadata)
0478: */
0479: private void applyJndiEnvironmentRefsGroup(
0480: final AbsEnvironment envGroup,
0481: final ClassAnnotationMetadata classAnnotationMetadata) {
0482:
0483: // post-construct / pre-destroy
0484: applyLifeCycle(envGroup.getPostConstructCallbackList(),
0485: classAnnotationMetadata, POST_CONSTRUCT);
0486: applyLifeCycle(envGroup.getPreDestroyCallbackList(),
0487: classAnnotationMetadata, PRE_DESTROY);
0488: applyLifeCycle(envGroup.getPrePassivateCallbackList(),
0489: classAnnotationMetadata, PRE_PASSIVATE);
0490: applyLifeCycle(envGroup.getPostActivateCallbackList(),
0491: classAnnotationMetadata, POST_ACTIVATE);
0492: applyAroundInvoke(envGroup.getAroundInvokeList(),
0493: classAnnotationMetadata, AroundInvoke.NAME);
0494:
0495: // ejb(local) ref
0496: applyEjbRef(envGroup.getEJBRefList(), classAnnotationMetadata);
0497: applyEjbLocalRef(envGroup.getEJBLocalRefList(),
0498: classAnnotationMetadata);
0499:
0500: // resource(env) ref
0501: applyResourceRef(envGroup.getResourceRefList(),
0502: classAnnotationMetadata);
0503: applyResourceEnvRef(envGroup.getResourceEnvRefList(),
0504: classAnnotationMetadata);
0505:
0506: // message-destination-ref
0507: applyMessageDestinationRef(envGroup
0508: .getMessageDestinationRefList(),
0509: classAnnotationMetadata);
0510:
0511: }
0512:
0513: /**
0514: * Apply rules for a common bean (message-destination-ref).
0515: * @param messageDestinationRefList the list of message-destination-ref.
0516: * @param classAnnotationMetadata (Annotation metadata) of the bean using
0517: * this interceptor (may be null).
0518: */
0519: private void applyMessageDestinationRef(
0520: final List<MessageDestinationRef> messageDestinationRefList,
0521: final ClassAnnotationMetadata classAnnotationMetadata) {
0522: if (messageDestinationRefList == null) {
0523: return;
0524: }
0525:
0526: // For each message-destination-ref, build a @{@link javax.annotation.Resource}
0527: for (MessageDestinationRef messageDestinationRef : messageDestinationRefList) {
0528: JAnnotationResource jResource = new JAnnotationResource();
0529: // set name
0530: jResource.setName(messageDestinationRef.getName());
0531:
0532: // set type
0533: jResource.setType(messageDestinationRef.getType());
0534:
0535: // Mapped Name
0536: jResource.setMappedName(messageDestinationRef
0537: .getMappedName());
0538:
0539: // Apply the resource on the class
0540: applyJResource(jResource, classAnnotationMetadata,
0541: messageDestinationRef.getInjectionTargetList());
0542: }
0543: }
0544:
0545: /**
0546: * Apply rules for a common bean (resource-ref).
0547: * @param resourceRefList the list of resource-ref.
0548: * @param classAnnotationMetadata (Annotation metadata) of the bean using
0549: * this interceptor (may be null).
0550: */
0551: private void applyResourceRef(
0552: final List<ResourceRef> resourceRefList,
0553: final ClassAnnotationMetadata classAnnotationMetadata) {
0554: if (resourceRefList == null) {
0555: return;
0556: }
0557:
0558: // For each resource-ref, build a @{@link javax.annotation.Resource}
0559: for (ResourceRef resourceRef : resourceRefList) {
0560: JAnnotationResource jResource = new JAnnotationResource();
0561: // set name
0562: jResource.setName(resourceRef.getResRefName());
0563:
0564: // set type
0565: jResource.setType(resourceRef.getResRefType());
0566:
0567: // Mapped Name
0568: jResource.setMappedName(resourceRef.getMappedName());
0569:
0570: // Apply the resource on the class
0571: applyJResource(jResource, classAnnotationMetadata,
0572: resourceRef.getInjectionTargetList());
0573: }
0574: }
0575:
0576: /**
0577: * Apply rules for a common bean (resource-env-ref).
0578: * @param resourceEnvRefList the list of resource-env-ref.
0579: * @param classAnnotationMetadata (Annotation metadata) of the bean using
0580: * this interceptor (may be null).
0581: */
0582: private void applyResourceEnvRef(
0583: final List<ResourceEnvRef> resourceEnvRefList,
0584: final ClassAnnotationMetadata classAnnotationMetadata) {
0585: if (resourceEnvRefList == null) {
0586: return;
0587: }
0588:
0589: // For each resource-ref, build a @{@link javax.annotation.Resource}
0590: for (ResourceEnvRef resourceEnvRef : resourceEnvRefList) {
0591: JAnnotationResource jResource = new JAnnotationResource();
0592: // set name
0593: jResource.setName(resourceEnvRef.getResourceEnvRefName());
0594:
0595: // set type
0596: jResource.setType(resourceEnvRef.getResourceEnvRefType());
0597:
0598: // Mapped Name
0599: jResource.setMappedName(resourceEnvRef.getMappedName());
0600:
0601: // Apply the resource on the class
0602: applyJResource(jResource, classAnnotationMetadata,
0603: resourceEnvRef.getInjectionTargetList());
0604: }
0605: }
0606:
0607: /**
0608: * Apply rules for a common bean (ejb-ref).
0609: * @param ejbRefList the list of ejb-ref.
0610: * @param classAnnotationMetadata (Annotation metadata) of the bean using
0611: * this interceptor (may be null).
0612: */
0613: private void applyEjbRef(final List<EJBRef> ejbRefList,
0614: final ClassAnnotationMetadata classAnnotationMetadata) {
0615: if (ejbRefList == null) {
0616: return;
0617: }
0618:
0619: // For each ejb-ref, build a @{@link javax.ejb.EJB}
0620: for (EJBRef ejbRef : ejbRefList) {
0621: JEjbEJB jEJB = buildEJB(ejbRef);
0622: // set interface
0623: if (ejbRef.getHome() != null) {
0624: jEJB.setBeanInterface(ejbRef.getHome());
0625: } else if (ejbRef.getRemote() != null) {
0626: jEJB.setBeanInterface(ejbRef.getRemote());
0627: }
0628: applyJEJB(jEJB, classAnnotationMetadata, ejbRef
0629: .getInjectionTargetList());
0630: }
0631: }
0632:
0633: /**
0634: * Apply rules for a common bean (ejb-local-ref).
0635: * @param ejbLocalRefList the list of ejb-local-ref.
0636: * @param classAnnotationMetadata (Annotation metadata) of the bean using
0637: * this interceptor (may be null).
0638: */
0639: private void applyEjbLocalRef(
0640: final List<EJBLocalRef> ejbLocalRefList,
0641: final ClassAnnotationMetadata classAnnotationMetadata) {
0642: if (ejbLocalRefList == null) {
0643: return;
0644: }
0645:
0646: // For each ejb-local-ref, build a @{@link javax.ejb.EJB}
0647: for (EJBLocalRef ejbLocalRef : ejbLocalRefList) {
0648: JEjbEJB jEJB = buildEJB(ejbLocalRef);
0649: // set interface
0650: if (ejbLocalRef.getLocalHome() != null) {
0651: jEJB.setBeanInterface(ejbLocalRef.getLocalHome());
0652: } else if (ejbLocalRef.getLocal() != null) {
0653: jEJB.setBeanInterface(ejbLocalRef.getLocal());
0654: }
0655: applyJEJB(jEJB, classAnnotationMetadata, ejbLocalRef
0656: .getInjectionTargetList());
0657: }
0658: }
0659:
0660: /**
0661: * Adds the given @{@link javax.annotation.Resource} object to the
0662: * class and apply it also on injection target elements.
0663: * @param jResource an @{@link javax.annotation.Resource} impl
0664: * @param classAnnotationMetadata the bean's class
0665: * @param injectionTargetList the list of injection fields to set
0666: */
0667: private static void applyJResource(
0668: final JAnnotationResource jResource,
0669: final ClassAnnotationMetadata classAnnotationMetadata,
0670: final List<InjectionTarget> injectionTargetList) {
0671:
0672: // Add field on the class
0673: JAnnotationResource existingJResource = classAnnotationMetadata
0674: .getJAnnotationResource();
0675:
0676: // Needs to use a list instead.
0677: List<JAnnotationResource> jResources = classAnnotationMetadata
0678: .getJAnnotationResources();
0679: if (jResources == null) {
0680: jResources = new ArrayList<JAnnotationResource>();
0681: classAnnotationMetadata.setJAnnotationResources(jResources);
0682: }
0683:
0684: // put existing element in the list
0685: if (existingJResource != null) {
0686: jResources.add(existingJResource);
0687: // remove single element
0688: classAnnotationMetadata.setJAnnotationResource(null);
0689: }
0690:
0691: // Add our new element
0692: jResources.add(jResource);
0693:
0694: // Now, add elements on the injection fields
0695: if (injectionTargetList != null) {
0696: for (InjectionTarget injectionTarget : injectionTargetList) {
0697:
0698: // Add the JAnnotationResource on it
0699: getInjectionTarget(classAnnotationMetadata,
0700: injectionTarget).setJAnnotationResource(
0701: jResource);
0702: }
0703: }
0704:
0705: }
0706:
0707: /**
0708: * Gets the metadata for a given injection target.
0709: * @param classAnnotationMetadata the class used to search the target
0710: * element
0711: * @param injectionTarget the given target info element
0712: * @return a common annotation metadata if element is found
0713: */
0714: private static CommonAnnotationMetadata getInjectionTarget(
0715: final ClassAnnotationMetadata classAnnotationMetadata,
0716: final InjectionTarget injectionTarget) {
0717: String injectionTargetName = injectionTarget.getTargetName();
0718:
0719: // First, try with the method
0720: MethodAnnotationMetadata method = getMethod(
0721: classAnnotationMetadata, injectionTarget);
0722:
0723: // found ? return it
0724: if (method != null) {
0725: return method;
0726: }
0727:
0728: // else, try with the next item which should be a field
0729: // Try with the field
0730: FieldAnnotationMetadata field = getField(
0731: classAnnotationMetadata, injectionTarget);
0732: if (field == null) {
0733: throw new IllegalArgumentException(
0734: "No field for injection target name '"
0735: + injectionTargetName
0736: + "' found in the class '"
0737: + classAnnotationMetadata.getClassName()
0738: + "'.");
0739: }
0740:
0741: return field;
0742:
0743: }
0744:
0745: /**
0746: * Gets the method metadata for a given injection target.
0747: * @param classAnnotationMetadata the class used to search the target
0748: * element
0749: * @param injectionTarget the given target info element
0750: * @return a method metadata if element is found
0751: */
0752: private static MethodAnnotationMetadata getMethod(
0753: final ClassAnnotationMetadata classAnnotationMetadata,
0754: final InjectionTarget injectionTarget) {
0755: // get data from the injection target element
0756: String clName = injectionTarget.getClassname();
0757: if (clName == null) {
0758: clName = classAnnotationMetadata.getClassName();
0759: } else {
0760: clName = clName.replace(".", "/");
0761: }
0762:
0763: // Get method name which is the injection target name
0764: String methodName = injectionTarget.getTargetName();
0765:
0766: // Now, search the element in the given class
0767: ClassAnnotationMetadata foundClassMetadata = classAnnotationMetadata
0768: .getEjbJarAnnotationMetadata()
0769: .getClassAnnotationMetadata(clName);
0770: if (foundClassMetadata == null) {
0771: throw new IllegalArgumentException(
0772: "Cannot find the class metadata named '" + clName
0773: + "'.");
0774: }
0775:
0776: // Got the class metadata, now search the field
0777: List<MethodAnnotationMetadata> methods = foundClassMetadata
0778: .searchMethodAnnotationMetadata(methodName);
0779:
0780: if (methods.size() == 0) {
0781: // no method
0782: return null;
0783: } else if (methods.size() > 1) {
0784: // Should be only one
0785: throw new IllegalArgumentException(
0786: "Too many methods with name '" + methodName
0787: + "' found in the class '" + clName + "'.");
0788: }
0789:
0790: return methods.get(0);
0791: }
0792:
0793: /**
0794: * Gets the field metadata for a given injection target.
0795: * @param classAnnotationMetadata the class used to search the target
0796: * element
0797: * @param injectionTarget the given target info element
0798: * @return a field if element is found
0799: */
0800: private static FieldAnnotationMetadata getField(
0801: final ClassAnnotationMetadata classAnnotationMetadata,
0802: final InjectionTarget injectionTarget) {
0803: // get data from the injection target element
0804: String clName = injectionTarget.getClassname();
0805: if (clName == null) {
0806: clName = classAnnotationMetadata.getClassName();
0807: } else {
0808: clName = clName.replace(".", "/");
0809: }
0810:
0811: String fieldName = injectionTarget.getTargetName();
0812:
0813: // Now, search the element in the given class
0814: ClassAnnotationMetadata foundClassMetadata = classAnnotationMetadata
0815: .getEjbJarAnnotationMetadata()
0816: .getClassAnnotationMetadata(clName);
0817: if (foundClassMetadata == null) {
0818: throw new IllegalArgumentException(
0819: "Cannot find the class metadata named '" + clName
0820: + "'.");
0821: }
0822:
0823: // Got the class metadata, now search the field
0824: List<FieldAnnotationMetadata> fields = foundClassMetadata
0825: .searchFieldAnnotationMetadata(fieldName);
0826:
0827: if (fields.size() == 0) {
0828: // no field
0829: return null;
0830: } else if (fields.size() > 1) {
0831: // Should be only one
0832: throw new IllegalArgumentException(
0833: "Too many fields with name '" + fieldName
0834: + "' found in the class '" + clName + "'.");
0835: }
0836:
0837: return fields.get(0);
0838: }
0839:
0840: /**
0841: * Adds the given @{@link javax.ejb.EJB} object to the class and apply
0842: * it also on injection target elements.
0843: * @param jEJB an @{@link javax.ejb.EJB} impl
0844: * @param classAnnotationMetadata the bean's class
0845: * @param injectionTargetList the list of injection fields to set
0846: */
0847: private static void applyJEJB(final JEjbEJB jEJB,
0848: final ClassAnnotationMetadata classAnnotationMetadata,
0849: final List<InjectionTarget> injectionTargetList) {
0850:
0851: // Add field on the class
0852: JEjbEJB existingJEjbEJB = classAnnotationMetadata.getJEjbEJB();
0853:
0854: // Needs to use a list instead.
0855: List<JEjbEJB> jEjbEJBs = classAnnotationMetadata.getJEjbEJBs();
0856: if (jEjbEJBs == null) {
0857: jEjbEJBs = new ArrayList<JEjbEJB>();
0858: classAnnotationMetadata.setJEjbEJBs(jEjbEJBs);
0859: }
0860:
0861: // put existing element in the list
0862: if (existingJEjbEJB != null) {
0863: jEjbEJBs.add(existingJEjbEJB);
0864: // remove single element
0865: classAnnotationMetadata.setJEjbEJB(null);
0866: }
0867:
0868: // Add our new element
0869: jEjbEJBs.add(jEJB);
0870:
0871: // Now, add elements on the injection fields
0872: if (injectionTargetList != null) {
0873: for (InjectionTarget injectionTarget : injectionTargetList) {
0874:
0875: // Add the JEjbEJB on it
0876: getInjectionTarget(classAnnotationMetadata,
0877: injectionTarget).setJEjbEJB(jEJB);
0878: }
0879: }
0880:
0881: }
0882:
0883: /**
0884: * Build an @{@link javax.ejb.EJB} impl for the given
0885: * ejb-ref/ejb-local-ref.
0886: * @param ref an instance of a ejb-ref/ejb-local-ref.
0887: * @return a implementation of @{@link javax.ejb.EJB} interface.
0888: */
0889: private static JEjbEJB buildEJB(final AbsEJBRef ref) {
0890: JEjbEJB jEJB = new JEjbEJB();
0891: // Sets the name
0892: if (ref.getEjbRefName() != null) {
0893: jEJB.setName(ref.getEjbRefName());
0894: }
0895:
0896: // sets the mapped-name
0897: if (ref.getMappedName() != null) {
0898: jEJB.setMappedName(ref.getMappedName());
0899: }
0900:
0901: // sets the bean-name
0902: if (ref.getEjbLink() != null) {
0903: jEJB.setBeanName(ref.getEjbLink());
0904: }
0905:
0906: return jEJB;
0907: }
0908:
0909: /**
0910: * Apply rules for a common bean (method callbacks).
0911: * @param aroundInvokeList the list of method/aroundInvoke callbacks.
0912: * @param classAnnotationMetadata (Annotation metadata) of the bean using
0913: * this interceptor (may be null).
0914: * @param type the type of lifecycle.
0915: */
0916: private void applyAroundInvoke(
0917: final List<AroundInvoke> aroundInvokeList,
0918: final ClassAnnotationMetadata classAnnotationMetadata,
0919: final String type) {
0920: for (AroundInvoke aroundInvoke : aroundInvokeList) {
0921: String interceptorClassName = null;
0922:
0923: // if no class, takes the bean's class
0924: if (aroundInvoke.getClassName() == null) {
0925: interceptorClassName = classAnnotationMetadata
0926: .getClassName();
0927: } else {
0928: interceptorClassName = encode(aroundInvoke
0929: .getClassName());
0930: }
0931:
0932: // Now, search the Method on the class or its super-class if not
0933: // found
0934: String searchMethodName = aroundInvoke.getMethodName();
0935: if (searchMethodName == null) {
0936: throw new IllegalStateException(
0937: "Invalid null method name for the callback '"
0938: + interceptorClassName + "'.");
0939: }
0940:
0941: // Apply interceptor
0942: applyInterceptor(type, interceptorClassName,
0943: searchMethodName, classAnnotationMetadata);
0944:
0945: }
0946: }
0947:
0948: /**
0949: * Apply rules for a common bean (lifecycle callbacks).
0950: * @param lifecycleList the list of lifecycle callbacks.
0951: * @param classAnnotationMetadata (Annotation metadata) of the bean using
0952: * this interceptor (may be null).
0953: * @param type the type of lifecycle.
0954: */
0955: private void applyLifeCycle(
0956: final List<LifeCycleCallback> lifecycleList,
0957: final ClassAnnotationMetadata classAnnotationMetadata,
0958: final String type) {
0959: for (LifeCycleCallback lifecycleCallback : lifecycleList) {
0960:
0961: String interceptorClassName = null;
0962:
0963: // if no class, takes the bean's class
0964: if (lifecycleCallback.getLifecycleCallbackClass() == null) {
0965: interceptorClassName = classAnnotationMetadata
0966: .getClassName();
0967: } else {
0968: interceptorClassName = encode(lifecycleCallback
0969: .getLifecycleCallbackClass());
0970: }
0971:
0972: // Now, search the Method on the class or its super-class if not
0973: // found
0974: String searchMethodName = lifecycleCallback
0975: .getLifecycleCallbackMethod();
0976: if (searchMethodName == null) {
0977: throw new IllegalStateException(
0978: "Invalid null method name for the callback '"
0979: + interceptorClassName + "'.");
0980: }
0981:
0982: // Apply interceptor
0983: applyInterceptor(type, interceptorClassName,
0984: searchMethodName, classAnnotationMetadata);
0985:
0986: }
0987: }
0988:
0989: /**
0990: * Adds a link on the given class to the interceptor class.
0991: * @param classAnnotationMetadata the class that will use/import the
0992: * interceptor
0993: * @param interceptorClassName the interceptor class.
0994: */
0995: private void addInterceptorForClass(
0996: final ClassAnnotationMetadata classAnnotationMetadata,
0997: final String interceptorClassName) {
0998: // Get interceptors for the given class (the bean class)
0999: JInterceptors interceptors = classAnnotationMetadata
1000: .getAnnotationInterceptors();
1001: if (interceptors == null) {
1002: // build new list if empty
1003: interceptors = new JInterceptors();
1004: classAnnotationMetadata
1005: .setAnnotationsInterceptors(interceptors);
1006: }
1007:
1008: // class already present ?
1009: if (!interceptors.contains(interceptorClassName)) {
1010: interceptors.addClass(interceptorClassName);
1011: }
1012: }
1013:
1014: /**
1015: * Finds a method in the interceptor class and set the correct type value.
1016: * @param type type of interceptor
1017: * @param interceptorClassName the name of the interceptor class
1018: * @param methodName the name of the method in the interceptor class
1019: * @param classAnnotationMetadata the class that is using the interceptor
1020: * (may be null)
1021: */
1022: private void applyInterceptor(final String type,
1023: final String interceptorClassName, final String methodName,
1024: final ClassAnnotationMetadata classAnnotationMetadata) {
1025:
1026: // if the bean is using this interceptor and that this is not the bean
1027: // class, add the link.
1028: if (classAnnotationMetadata != null
1029: && !classAnnotationMetadata.getClassName().equals(
1030: interceptorClassName)) {
1031: addInterceptorForClass(classAnnotationMetadata,
1032: interceptorClassName);
1033: }
1034:
1035: MethodAnnotationMetadata foundMethod = null;
1036: ClassAnnotationMetadata interceptorMetadata = ejbMetadata
1037: .getClassAnnotationMetadata(interceptorClassName);
1038:
1039: boolean loop = true;
1040: // While method is not found and that class has super class, try to
1041: // search
1042: while (foundMethod == null && loop) {
1043: List<MethodAnnotationMetadata> listMethods = interceptorMetadata
1044: .searchMethodAnnotationMetadata(methodName);
1045:
1046: // Method present ?
1047: if (listMethods.size() == 1) {
1048: // first item
1049: foundMethod = listMethods.get(0);
1050: continue;
1051: } else if (listMethods.size() > 1) {
1052: throw new IllegalStateException("Method with name '"
1053: + methodName
1054: + "' was found more than once on the class '"
1055: + interceptorMetadata.getClassName() + "'.");
1056: }
1057:
1058: // else continue
1059: String super ClassName = interceptorMetadata.getSuperName();
1060: if (!super ClassName.equals(JAVA_LANG_OBJECT)) {
1061: interceptorMetadata = ejbMetadata
1062: .getClassAnnotationMetadata(super ClassName);
1063: } else {
1064: // break loop
1065: loop = false;
1066: }
1067: }
1068:
1069: if (foundMethod == null) {
1070: throw new IllegalStateException("The method named '"
1071: + methodName + "' was not found in the class '"
1072: + interceptorMetadata.getClassName()
1073: + "' and all its super-classes.");
1074: }
1075:
1076: // call setter to true and only if it is not already present.
1077: if (POST_CONSTRUCT.equals(type)) {
1078: if (!foundMethod.isPostConstruct()) {
1079: foundMethod.setPostConstruct(true);
1080: interceptorMetadata
1081: .addPostConstructMethodMetadata(foundMethod);
1082: }
1083: } else if (PRE_DESTROY.equals(type)) {
1084: if (!foundMethod.isPreDestroy()) {
1085: foundMethod.setPreDestroy(true);
1086: interceptorMetadata
1087: .addPreDestroyMethodMetadata(foundMethod);
1088: }
1089: } else if (PRE_PASSIVATE.equals(type)) {
1090: if (!foundMethod.isPrePassivate()) {
1091: foundMethod.setPrePassivate(true);
1092: interceptorMetadata
1093: .addPrePassivateMethodMetadata(foundMethod);
1094: }
1095: } else if (POST_ACTIVATE.equals(type)) {
1096: if (!foundMethod.isPostActivate()) {
1097: foundMethod.setPostActivate(true);
1098: interceptorMetadata
1099: .addPostActivateMethodMetadata(foundMethod);
1100: }
1101: } else if (AroundInvoke.NAME.equals(type)) {
1102: if (!foundMethod.isAroundInvoke()) {
1103: foundMethod.setAroundInvoke(true);
1104: interceptorMetadata
1105: .addAroundInvokeMethodMetadata(foundMethod);
1106: }
1107: } else {
1108: throw new IllegalStateException("No case for type '" + type
1109: + "'..");
1110: }
1111: }
1112:
1113: /**
1114: * Find/Gets a classAnnotationMetadata for a given ejb name and/or a given
1115: * ejbclass name.
1116: * @param ejbName the name of the EJB.
1117: * @param ejbClass the class of the EJB.
1118: * @return a classAnnotationMetadata if found, else exception
1119: */
1120: private ClassAnnotationMetadata findClassForEjb(
1121: final String ejbName, final String ejbClass) {
1122: ClassAnnotationMetadata classAnnotationMetadata = null;
1123:
1124: // First, try with ejbClass if not null
1125: if (ejbClass != null) {
1126: classAnnotationMetadata = ejbMetadata
1127: .getClassAnnotationMetadata(encode(ejbClass));
1128: // found ? return it
1129: if (classAnnotationMetadata != null) {
1130: return classAnnotationMetadata;
1131: }
1132: }
1133:
1134: // else, needs to find a class with the specified name
1135: for (ClassAnnotationMetadata tmpMetaData : ejbMetadata
1136: .getClassAnnotationMetadataCollection()) {
1137: if (tmpMetaData.isBean()) {
1138: // check name
1139: JCommonBean bean = tmpMetaData.getJCommonBean();
1140: if (bean != null) {
1141: // found !
1142: if (ejbName != null
1143: && ejbName.equals(bean.getName())) {
1144: return tmpMetaData;
1145: }
1146: }
1147: }
1148: }
1149: throw new IllegalStateException("No class with ejb-name '"
1150: + ejbName + "' or ejb-class '" + ejbClass
1151: + "' was found in the EJB-JAR file '" + ejbMetadata);
1152: }
1153:
1154: /**
1155: * Set/override the current application-exception.
1156: * @param assemblyDescriptor the given assembly descriptor to analyze.
1157: */
1158: public void mergeApplicationException(
1159: final AssemblyDescriptor assemblyDescriptor) {
1160: List<JApplicationException> assemblyDescriptorList = assemblyDescriptor
1161: .getApplicationExceptionList();
1162: if (assemblyDescriptorList != null) {
1163: for (JApplicationException applicationException : assemblyDescriptorList) {
1164: String className = applicationException.getClassName();
1165: // Get metadata for the given class
1166: ClassAnnotationMetadata exceptionMetadata = ejbMetadata
1167: .getClassAnnotationMetadata(encode(className));
1168: if (exceptionMetadata == null) {
1169: throw new IllegalStateException(
1170: "The class named '"
1171: + className
1172: + "' was not found. Cannot set ApplicationException on it");
1173: }
1174: // Set the new value
1175: exceptionMetadata
1176: .setApplicationException(applicationException);
1177: logger
1178: .debug(
1179: "Setting the application-exception ''{0}'' on the class ''{1}''",
1180: applicationException, className);
1181: }
1182: }
1183: }
1184:
1185: /**
1186: * Set/override the current security.
1187: * @param assemblyDescriptor the given assembly descriptor to analyze.
1188: */
1189: public void mergeAssemblySecurity(
1190: final AssemblyDescriptor assemblyDescriptor) {
1191:
1192: // Search the security role
1193: List<String> securityRoles = assemblyDescriptor
1194: .getSecurityRoleList();
1195: for (String role : securityRoles) {
1196: // Gets the metadata for all ejb
1197: for (ClassAnnotationMetadata beanMetadata : ejbMetadata
1198: .getClassAnnotationMetadataCollection()) {
1199: if (beanMetadata.isBean()) {
1200: List<String> declaredRoles = beanMetadata
1201: .getDeclareRoles();
1202: if (declaredRoles == null) {
1203: declaredRoles = new ArrayList<String>();
1204: }
1205: if (!declaredRoles.contains(role)) {
1206: declaredRoles.add(role);
1207: beanMetadata.setDeclareRoles(declaredRoles);
1208: }
1209: }
1210: }
1211: }
1212:
1213: // sets the per-role or unchecked methods
1214: List<MethodPermission> methodPermissionList = assemblyDescriptor
1215: .getMethodPermissionList();
1216: for (MethodPermission methodPermission : methodPermissionList) {
1217:
1218: List<MethodDD> methodDDs = methodPermission.getMethods();
1219: for (MethodDD method : methodDDs) {
1220:
1221: // Get Ejb-Name
1222: String ejbName = method.getEjbName();
1223:
1224: // Gets the metadata for the ejb
1225: ClassAnnotationMetadata beanMetadata = ejbMetadata
1226: .getClassAnnotationMetadataForEjbName(ejbName);
1227: if (beanMetadata == null) {
1228: throw new IllegalStateException(
1229: "No metadata found for the the ejb '"
1230: + ejbName
1231: + "'. Check that this ejb is defined. This ejb-name is referenced from "
1232: + "a method of an assembly descriptor / method-permission");
1233: }
1234:
1235: // Get matching methods
1236: List<MethodAnnotationMetadata> methods = getMethodsForGivenMethodDD(
1237: method, beanMetadata);
1238:
1239: for (MethodAnnotationMetadata methodAnnotationMetadata : methods) {
1240: // Role -base or unchecked ?
1241: if (methodPermission.isUnchecked()) {
1242: methodAnnotationMetadata.setPermitAll(true);
1243: } else if (methodPermission.getRoleNameList()
1244: .size() > 0) {
1245: for (String role : methodPermission
1246: .getRoleNameList()) {
1247: List<String> existingRolesAllowed = methodAnnotationMetadata
1248: .getRolesAllowed();
1249: if (existingRolesAllowed == null) {
1250: existingRolesAllowed = new ArrayList<String>();
1251: }
1252: if (!existingRolesAllowed.contains(role)) {
1253: existingRolesAllowed.add(role);
1254: methodAnnotationMetadata
1255: .setRolesAllowed(existingRolesAllowed);
1256: }
1257: }
1258: }
1259: }
1260: }
1261: }
1262:
1263: // Exclude the given methods of the XML DD
1264: List<MethodDD> excludeMethodList = assemblyDescriptor
1265: .getExcludeListMethods();
1266: for (MethodDD method : excludeMethodList) {
1267:
1268: // Get Ejb-Name
1269: String ejbName = method.getEjbName();
1270:
1271: // Gets the metadata for the ejb
1272: ClassAnnotationMetadata beanMetadata = ejbMetadata
1273: .getClassAnnotationMetadataForEjbName(ejbName);
1274: if (beanMetadata == null) {
1275: throw new IllegalStateException(
1276: "No metadata found for the the ejb '"
1277: + ejbName
1278: + "'. Check that this ejb is defined. This ejb-name is referenced from "
1279: + "a method of an assembly descriptor / exclude-list");
1280: }
1281:
1282: // Get matching methods
1283: List<MethodAnnotationMetadata> methods = getMethodsForGivenMethodDD(
1284: method, beanMetadata);
1285:
1286: // Set the deny all flag to these methods
1287: for (MethodAnnotationMetadata methodAnnotationMetadata : methods) {
1288: methodAnnotationMetadata.setDenyAll(true);
1289: }
1290: }
1291: }
1292:
1293: /**
1294: * Set/override the current container-transaction.
1295: * @param assemblyDescriptor the given assembly descriptor to analyze.
1296: */
1297: public void mergeContainerTransaction(
1298: final AssemblyDescriptor assemblyDescriptor) {
1299: List<ContainerTransaction> containerTransactionList = assemblyDescriptor
1300: .getContainerTransactionList();
1301: if (containerTransactionList == null) {
1302: return;
1303: }
1304:
1305: for (ContainerTransaction containerTransaction : containerTransactionList) {
1306:
1307: // No transaction attribute ? then escape
1308: TransactionAttributeType transactionAttributeType = containerTransaction
1309: .getTransactionAttribute();
1310: if (transactionAttributeType == null) {
1311: continue;
1312: }
1313:
1314: for (MethodDD method : containerTransaction.getMethods()) {
1315: // Get Ejb-Name
1316: String ejbName = method.getEjbName();
1317:
1318: // Gets the metadata for the ejb
1319: ClassAnnotationMetadata beanMetadata = ejbMetadata
1320: .getClassAnnotationMetadataForEjbName(ejbName);
1321: if (beanMetadata == null) {
1322: throw new IllegalStateException(
1323: "No metadata found for the the ejb '"
1324: + ejbName
1325: + "'. Check that this ejb is defined. This ejb-name is referenced from "
1326: + "a method of a container transaction");
1327: }
1328:
1329: // Get Ejb-Name
1330: String methodName = method.getName();
1331: TransactionAttributeLevel txlevel = TransactionAttributeLevel.XML_WILDCARD;
1332:
1333: // Style 1 (see �13.3.7.2)
1334: if (WILDCARD.equals(methodName)) {
1335: // Apply tx for all methods if it can be applied
1336: for (MethodAnnotationMetadata methodAnnotationMetadata : beanMetadata
1337: .getMethodAnnotationMetadataCollection()) {
1338: // check level ?
1339: if (methodAnnotationMetadata
1340: .getTransactionAttributeLevel() == TransactionAttributeLevel.ANNOTATION) {
1341: methodAnnotationMetadata
1342: .setTransactionAttributeType(transactionAttributeType);
1343: methodAnnotationMetadata
1344: .setTransactionAttributeLevel(txlevel);
1345: logger
1346: .debug(
1347: "Setting transaction attribute of method {0} of bean {1} to {2}",
1348: methodAnnotationMetadata,
1349: ejbName,
1350: transactionAttributeType);
1351: }
1352:
1353: }
1354: // next step
1355: continue;
1356: }
1357:
1358: // Style 2 ?
1359: List<String> params = method.getParams();
1360:
1361: if (params.size() == 0) {
1362: txlevel = TransactionAttributeLevel.XML_METHOD_NAME;
1363: } else {
1364: txlevel = TransactionAttributeLevel.XML_METHOD_PARAMS;
1365: }
1366:
1367: // Get matching methods
1368: List<MethodAnnotationMetadata> methods = getMethodsForGivenMethodDD(
1369: method, beanMetadata);
1370: if (methods.size() == 0) {
1371: throw new IllegalStateException(
1372: "No matching method found with '" + method
1373: + "' for bean '" + ejbName + "'.");
1374: }
1375:
1376: for (MethodAnnotationMetadata methodAnnotationMetadata : methods) {
1377:
1378: // check level ?
1379: if (methodAnnotationMetadata
1380: .getTransactionAttributeLevel() == TransactionAttributeLevel.ANNOTATION
1381: || methodAnnotationMetadata
1382: .getTransactionAttributeLevel() == TransactionAttributeLevel.XML_WILDCARD) {
1383:
1384: if ((txlevel == TransactionAttributeLevel.XML_METHOD_NAME && methodAnnotationMetadata
1385: .getTransactionAttributeLevel() != TransactionAttributeLevel.XML_METHOD_PARAMS)
1386: || (txlevel == TransactionAttributeLevel.XML_METHOD_PARAMS)) {
1387: methodAnnotationMetadata
1388: .setTransactionAttributeType(transactionAttributeType);
1389: methodAnnotationMetadata
1390: .setTransactionAttributeLevel(txlevel);
1391: logger
1392: .debug(
1393: "Setting transaction attribute of method {0} of bean {1} to {2}",
1394: methodAnnotationMetadata,
1395: ejbName, txlevel);
1396: }
1397: }
1398:
1399: }
1400: }
1401: }
1402: }
1403:
1404: /**
1405: * Set/override the current interceptor-binding.
1406: * @param assemblyDescriptor the given assembly descriptor to analyze.
1407: */
1408: public void mergeInterceptorBinding(
1409: final AssemblyDescriptor assemblyDescriptor) {
1410: List<InterceptorBinding> interceptorBindingList = assemblyDescriptor
1411: .getInterceptorBindingList();
1412: if (interceptorBindingList != null) {
1413: for (InterceptorBinding interceptorBinding : interceptorBindingList) {
1414:
1415: // Get Ejb-Name
1416: String ejbName = interceptorBinding.getEjbName();
1417: // Default interceptor
1418: if (WILDCARD.equals(ejbName)) {
1419: // Get current list
1420: JInterceptors defaultInterceptors = ejbMetadata
1421: .getDefaultInterceptorsClasses();
1422: if (defaultInterceptors == null) {
1423: // build new list if empty
1424: defaultInterceptors = new JInterceptors();
1425: ejbMetadata
1426: .setDefaultInterceptorsClasses(defaultInterceptors);
1427: }
1428:
1429: // Add the interceptors of the interceptor-binding to the
1430: // default interceptors
1431: for (String interceptor : interceptorBinding
1432: .getInterceptorClassList()) {
1433: defaultInterceptors
1434: .addClass(encode(interceptor));
1435: }
1436:
1437: // stop the loop
1438: continue;
1439: }
1440:
1441: // Gets the metadata for the ejb
1442: ClassAnnotationMetadata beanMetadata = ejbMetadata
1443: .getClassAnnotationMetadataForEjbName(ejbName);
1444: if (beanMetadata == null) {
1445: throw new IllegalStateException(
1446: "No metadata found for the the ejb '"
1447: + ejbName
1448: + "'. Check that this ejb is defined. This ejb-name is referenced from an interceptor-binding");
1449: }
1450:
1451: // It is a method ?
1452: MethodDD methodDD = interceptorBinding.getMethod();
1453:
1454: // not a method
1455: if (methodDD == null) {
1456: JInterceptors interceptors = beanMetadata
1457: .getAnnotationInterceptors();
1458: if (interceptors == null) {
1459: // build new list if empty
1460: interceptors = new JInterceptors();
1461: beanMetadata
1462: .setAnnotationsInterceptors(interceptors);
1463: }
1464:
1465: for (String interceptor : interceptorBinding
1466: .getInterceptorClassList()) {
1467: interceptors.addClass(encode(interceptor));
1468: }
1469:
1470: // Exclude default interceptors for this bean ?
1471: if (interceptorBinding
1472: .isExcludeDefaultInterceptorsCalled()) {
1473: beanMetadata
1474: .setExcludeDefaultInterceptors(interceptorBinding
1475: .isExcludeDefaultInterceptors());
1476: }
1477:
1478: // For ordered item: First, add interceptors (if they are
1479: // not already present)
1480: List<String> orderList = interceptorBinding
1481: .getOrderInterceptorClassList();
1482: if (orderList != null) {
1483:
1484: // Check that this is the first time that we try to
1485: // order the list.
1486: if (beanMetadata.isOrderedInterceptors()) {
1487: throw new IllegalStateException(
1488: "The interceptor-order element has already been used on the bean '"
1489: + ejbName
1490: + "'. It can only be used once.");
1491: }
1492:
1493: // Flag class as a class having ordered interceptors
1494: beanMetadata.setOrderedInterceptors(true);
1495:
1496: // Build a list with all interceptors. (it means that we
1497: // add default interceptors if any) if they are not
1498: // excluded
1499: if (!beanMetadata
1500: .isExcludedDefaultInterceptors()) {
1501: if (beanMetadata
1502: .getEjbJarAnnotationMetadata()
1503: .getDefaultInterceptorsClasses() != null) {
1504: for (String cls : beanMetadata
1505: .getEjbJarAnnotationMetadata()
1506: .getDefaultInterceptorsClasses()
1507: .getClasses()) {
1508: interceptors.addClass(cls);
1509: }
1510: }
1511: }
1512:
1513: // Then add new items found in the DD
1514: for (String interceptor : interceptorBinding
1515: .getOrderInterceptorClassList()) {
1516: String encodedName = encode(interceptor);
1517: if (!interceptors.contains(encodedName)) {
1518: interceptors.addClass(encodedName);
1519: }
1520: }
1521:
1522: // Order.
1523: // First, check that the list has the correct size as it
1524: // should be a total ordering.
1525: if (interceptors.size() != orderList.size()) {
1526: String err = "The list used for ordering interceptors is not a total list as the size mismatch.";
1527: err += "The current list is '"
1528: + interceptors
1529: + "' while the ordering list is '"
1530: + orderList + "'.";
1531: throw new IllegalStateException(err);
1532: }
1533:
1534: // Size is ok, check that all elements are present
1535: for (String clazz : orderList) {
1536: if (!interceptors.contains(encode(clazz))) {
1537: throw new IllegalStateException(
1538: "The element '"
1539: + clazz
1540: + "' of the ordered list is not present in the interceptors '"
1541: + interceptors + "'.");
1542: }
1543: }
1544:
1545: // Ok, all the elements are present, set the new
1546: // ordering.
1547: // Which is based on the given ordered list.
1548: JInterceptors orderedInterceptors = new JInterceptors();
1549: for (String clazz : orderList) {
1550: orderedInterceptors.addClass(encode(clazz));
1551: }
1552: // Set the new list
1553: beanMetadata
1554: .setAnnotationsInterceptors(orderedInterceptors);
1555:
1556: }
1557: } else {
1558: // method case
1559: List<MethodAnnotationMetadata> methods = getMethodsForGivenMethodDD(
1560: methodDD, beanMetadata);
1561:
1562: // If no elements, print warning
1563: if (methods.size() == 0) {
1564: logger
1565: .warn("Method with name '"
1566: + methodDD.getName()
1567: + "' is specified in interceptorBinding element for class '"
1568: + beanMetadata.getClassName()
1569: + "' but no methods are matching");
1570: }
1571:
1572: // now, apply interceptor on each method
1573: for (MethodAnnotationMetadata method : methods) {
1574: JInterceptors interceptors = method
1575: .getAnnotationInterceptors();
1576: if (interceptors == null) {
1577: // build new list if empty
1578: interceptors = new JInterceptors();
1579: method
1580: .setAnnotationsInterceptors(interceptors);
1581: }
1582:
1583: for (String interceptor : interceptorBinding
1584: .getInterceptorClassList()) {
1585: interceptors.addClass(encode(interceptor));
1586: }
1587:
1588: // Exclude class interceptors for this method ?
1589: if (interceptorBinding
1590: .isExcludeClassInterceptorsCalled()) {
1591: method
1592: .setExcludeClassInterceptors(interceptorBinding
1593: .isExcludeClassInterceptors());
1594: }
1595: // Exclude default interceptors for this method ?
1596: if (interceptorBinding
1597: .isExcludeDefaultInterceptorsCalled()) {
1598: method
1599: .setExcludeDefaultInterceptors(interceptorBinding
1600: .isExcludeDefaultInterceptors());
1601: }
1602:
1603: }
1604: }
1605: }
1606: }
1607: }
1608:
1609: /**
1610: * Gets the methods metadata that are matching a given method DD.
1611: * @param methodDD the methodDD object
1612: * @param classAnnotationMetadata the class where to search methods.
1613: * @return the list of methods metadata
1614: */
1615: private static List<MethodAnnotationMetadata> getMethodsForGivenMethodDD(
1616: final MethodDD methodDD,
1617: final ClassAnnotationMetadata classAnnotationMetadata) {
1618: // get the method.
1619: String methodName = methodDD.getName();
1620: List<MethodAnnotationMetadata> methods = classAnnotationMetadata
1621: .searchMethodAnnotationMetadata(methodName);
1622: // params ?
1623: List<String> params = methodDD.getParams();
1624: // Keep only method with the correct params
1625: if (params != null && params.size() > 0) {
1626: List<MethodAnnotationMetadata> newMethods = new ArrayList<MethodAnnotationMetadata>();
1627: for (MethodAnnotationMetadata method : methods) {
1628: // get params for the current method
1629: Type[] types = Type.getArgumentTypes(method
1630: .getJMethod().getDescriptor());
1631: // Same size ?
1632: if (params.size() != types.length) {
1633: // Not same size, go to the next one
1634: continue;
1635: }
1636:
1637: // Compare each element
1638: int i = 0;
1639: boolean matching = false;
1640: for (String param : params) {
1641: if (param.equals(types[i].getClassName())) {
1642: matching = true;
1643: }
1644: i++;
1645: }
1646: // match ?
1647: if (matching) {
1648: newMethods.add(method);
1649: }
1650: }
1651: // Get the new list (only matching elements)
1652: methods = newMethods;
1653: }
1654: return methods;
1655: }
1656:
1657: /**
1658: * Encode a classname (replace . by /) as it's the internal form of the
1659: * metadata
1660: * @param className the name of the class to encode
1661: * @return encoded name
1662: */
1663: private static String encode(final String className) {
1664: return className.replace(".", "/");
1665: }
1666: }
|