Package org.jboss.as.ejb3.deployment.processors.dd

Source Code of org.jboss.as.ejb3.deployment.processors.dd.EjbConcurrencyProcessor

/*
* JBoss, Home of Professional Open Source
* Copyright 2010, Red Hat Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.as.ejb3.deployment.processors.dd;

import org.jboss.as.ee.component.Attachments;
import org.jboss.as.ee.component.ComponentDescription;
import org.jboss.as.ee.component.EEModuleDescription;
import org.jboss.as.ejb3.component.session.SessionBeanComponentDescription;
import org.jboss.as.ejb3.component.singleton.SingletonComponentDescription;
import org.jboss.as.ejb3.component.stateful.StatefulComponentDescription;
import org.jboss.as.ejb3.deployment.EjbDeploymentAttachmentKeys;
import org.jboss.as.server.deployment.DeploymentPhaseContext;
import org.jboss.as.server.deployment.DeploymentUnit;
import org.jboss.as.server.deployment.DeploymentUnitProcessingException;
import org.jboss.as.server.deployment.DeploymentUnitProcessor;
import org.jboss.as.server.deployment.reflect.ClassReflectionIndex;
import org.jboss.as.server.deployment.reflect.DeploymentReflectionIndex;
import org.jboss.invocation.proxy.MethodIdentifier;
import org.jboss.metadata.ejb.spec.AccessTimeoutMetaData;
import org.jboss.metadata.ejb.spec.ConcurrentMethodMetaData;
import org.jboss.metadata.ejb.spec.ConcurrentMethodsMetaData;
import org.jboss.metadata.ejb.spec.EjbJarMetaData;
import org.jboss.metadata.ejb.spec.EnterpriseBeanMetaData;
import org.jboss.metadata.ejb.spec.NamedMethodMetaData;
import org.jboss.metadata.ejb.spec.SessionBean31MetaData;
import org.jboss.modules.Module;

import javax.ejb.AccessTimeout;
import javax.ejb.Lock;
import javax.ejb.LockType;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
* DUP that processes concurrency information for singleton beans.
* <p/>
* It checks to make sure that concurrency annotations have not been overriden by a sub class,
* and then parses ejb-jar.xml to read concurrency information from the descriptor.
* We cannot check if methods have been overriden until we can actually load the class.
* <p/>
* from ejb-jar.xml.
*
* @author Stuart Douglas
*/
public class EjbConcurrencyProcessor implements DeploymentUnitProcessor {

    @Override
    public void deploy(final DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
        final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
        final EjbJarMetaData ejbJarMetaData = deploymentUnit.getAttachment(EjbDeploymentAttachmentKeys.EJB_JAR_METADATA);
        final EEModuleDescription eeModuleDescription = deploymentUnit.getAttachment(Attachments.EE_MODULE_DESCRIPTION);
        final Module module = deploymentUnit.getAttachment(org.jboss.as.server.deployment.Attachments.MODULE);
        final DeploymentReflectionIndex index = deploymentUnit.getAttachment(org.jboss.as.server.deployment.Attachments.REFLECTION_INDEX);

        if(eeModuleDescription == null) {
            return;
        }

        for (ComponentDescription description : eeModuleDescription.getComponentDescriptions()) {
            if (description instanceof SingletonComponentDescription || description instanceof StatefulComponentDescription) {
                try {
                    Class<?> componentClass = module.getClassLoader().loadClass(description.getComponentClassName());
                    checkMethodOverrides(componentClass, (SessionBeanComponentDescription) description, index);

                    if (ejbJarMetaData != null) {
                        EnterpriseBeanMetaData bean = ejbJarMetaData.getEnterpriseBean(((SessionBeanComponentDescription)description).getEJBName());
                        if (bean instanceof SessionBean31MetaData) {
                            processBean((SessionBean31MetaData) bean, (SessionBeanComponentDescription) description, index, componentClass);
                        }
                    }

                } catch (ClassNotFoundException e) {
                    throw new DeploymentUnitProcessingException("Could not load EJB class " + description.getComponentClassName(), e);
                }
            }
        }

    }

    /**
     * Removes annotation information from a class if the method has been overridden with a method that has no annotation,
     * as the jandex index cannot be used to get information about methods with no annotations
     */
    private void checkMethodOverrides(final Class<?> componentClass, final SessionBeanComponentDescription description, final DeploymentReflectionIndex index) {

        ClassReflectionIndex<?> classIndex = index.getClassIndex(componentClass);
        Iterator<Map.Entry<MethodIdentifier, LockType>> iterator = description.getMethodApplicableLockTypes().entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<MethodIdentifier, LockType> entry = iterator.next();
            if (annotationOverridden(classIndex, index, entry.getKey(), Lock.class)) {
                iterator.remove();
            }
        }
        Iterator<Map.Entry<MethodIdentifier, AccessTimeout>> iterator2 = description.getMethodApplicableAccessTimeouts().entrySet().iterator();
        while (iterator2.hasNext()) {
            Map.Entry<MethodIdentifier, AccessTimeout> entry = iterator2.next();
            if (annotationOverridden(classIndex, index, entry.getKey(), AccessTimeout.class)) {
                iterator.remove();
            }
        }

    }

    private boolean annotationOverridden(final ClassReflectionIndex<?> classIndex, final DeploymentReflectionIndex index, final MethodIdentifier method, final Class<? extends Annotation> annotation) {
        ClassReflectionIndex<?> cindex = classIndex;
        while (cindex != null && cindex.getIndexedClass() != Object.class) {
            Method m = cindex.getMethod(method);
            if (m != null) {
                return !m.isAnnotationPresent(annotation);
            }
            cindex = index.getClassIndex(cindex.getIndexedClass().getSuperclass());
        }
        return false;
    }


    /**
     * Processes method level concurrency from the deployment descriptor.
     */
    private void processBean(SessionBean31MetaData singletonBeanMetaData, SessionBeanComponentDescription singletonComponentDescription, DeploymentReflectionIndex reflectionIndex, Class<?> componentClass) throws DeploymentUnitProcessingException {

        // add method level lock type to the description
        ConcurrentMethodsMetaData concurrentMethods = singletonBeanMetaData.getConcurrentMethods();
        if (concurrentMethods != null) {
            for (ConcurrentMethodMetaData concurrentMethod : concurrentMethods) {
                LockType methodLockType = concurrentMethod.getLockType();
                Method method = resolveMethod(reflectionIndex, (Class<Object>) componentClass, concurrentMethod.getMethod());
                final MethodIdentifier methodIdentifier = MethodIdentifier.getIdentifierForMethod(method);
                if(methodLockType != null) {
                    singletonComponentDescription.setLockType(methodLockType, methodIdentifier);
                }
                final AccessTimeoutMetaData accessTimeout = concurrentMethod.getAccessTimeout();
                if(accessTimeout != null) {
                    singletonComponentDescription.setAccessTimeout(new AccessTimeout() {
                        @Override
                        public long value() {
                            return accessTimeout.getTimeout();
                        }

                        @Override
                        public TimeUnit unit() {
                            return accessTimeout.getUnit();
                        }

                        @Override
                        public Class<? extends Annotation> annotationType() {
                            return AccessTimeout.class;
                        }
                    }, methodIdentifier);
                }
            }
        }

    }

    private Method resolveMethod(final DeploymentReflectionIndex index, final Class<Object> componentClass, final NamedMethodMetaData methodData) throws DeploymentUnitProcessingException {
        if(componentClass == null) {
            throw new DeploymentUnitProcessingException("Could not find method" + methodData.getMethodName() + "with parameter types" + methodData.getMethodParams() + " referenced in ejb-jar.xml");
        }
        final ClassReflectionIndex<?> classIndex = index.getClassIndex(componentClass);

        if (methodData.getMethodParams() == null) {
            final Collection<Method> methods = classIndex.getAllMethods(methodData.getMethodName());
            if (methods.isEmpty()) {
                return resolveMethod(index, (Class<Object>) componentClass.getSuperclass(), methodData);
            } else if (methods.size() > 1) {
                throw new DeploymentUnitProcessingException("More than one method " + methodData.getMethodName() + "found on class" + componentClass.getName() + " referenced in ejb-jar.xml. Specify the parameter types to resolve the ambiguity");
            }
            return methods.iterator().next();
        } else {
            final Collection<Method> methods = classIndex.getAllMethods(methodData.getMethodName(), methodData.getMethodParams().size());
            for (final Method method : methods) {
                boolean match = true;
                for (int i = 0; i < method.getParameterTypes().length; ++i) {
                    if (!method.getParameterTypes()[i].getName().equals(methodData.getMethodParams().get(i))) {
                        match = false;
                        break;
                    }
                }
                if (match) {
                    return method;
                }
            }
        }
        return resolveMethod(index, (Class<Object>) componentClass.getSuperclass(), methodData);
    }

    @Override
    public void undeploy(final DeploymentUnit context) {

    }
}
TOP

Related Classes of org.jboss.as.ejb3.deployment.processors.dd.EjbConcurrencyProcessor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.