Package org.jboss.as.ee.component.deployers

Source Code of org.jboss.as.ee.component.deployers.InterceptorsAnnotationParsingProcessor

/*
* JBoss, Home of Professional Open Source.
* Copyright 2010, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file 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.ee.component.deployers;

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.ee.component.InterceptorDescription;
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.annotation.CompositeIndex;
import org.jboss.invocation.proxy.MethodIdentifier;
import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.AnnotationTarget;
import org.jboss.jandex.AnnotationValue;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.DotName;
import org.jboss.jandex.MethodInfo;
import org.jboss.jandex.Type;

import javax.interceptor.ExcludeClassInterceptors;
import javax.interceptor.ExcludeDefaultInterceptors;
import javax.interceptor.Interceptors;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
* Deployment processor responsible for analyzing the annotation index to find all @Interceptors, @ExcludeDefaultInterceptors and
*
* @author John Bailey
*/
public class InterceptorsAnnotationParsingProcessor implements DeploymentUnitProcessor {
    private static final DotName INTERCEPTORS_ANNOTATION_NAME = DotName.createSimple(Interceptors.class.getName());
    private static final DotName EXCLUDE_DEFAULT_ANNOTATION_NAME = DotName.createSimple(ExcludeDefaultInterceptors.class.getName());
    private static final DotName EXCLUDE_CLASS_ANNOTATION_NAME = DotName.createSimple(ExcludeClassInterceptors.class.getName());

    public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
        final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
        final EEModuleDescription eeModuleDescription = deploymentUnit.getAttachment(Attachments.EE_MODULE_DESCRIPTION);
        final CompositeIndex index = deploymentUnit.getAttachment(org.jboss.as.server.deployment.Attachments.COMPOSITE_ANNOTATION_INDEX);

        final List<AnnotationInstance> interceptors = index.getAnnotations(INTERCEPTORS_ANNOTATION_NAME);
        for (AnnotationInstance annotation : interceptors) {
            processInterceptors(eeModuleDescription, annotation, index);
        }

        final List<AnnotationInstance> excludeDefaults = index.getAnnotations(EXCLUDE_DEFAULT_ANNOTATION_NAME);
        for (AnnotationInstance annotation : excludeDefaults) {
            processExcludeDefault(eeModuleDescription, annotation, index);
        }

        final List<AnnotationInstance> excludeClasses = index.getAnnotations(EXCLUDE_CLASS_ANNOTATION_NAME);
        for (AnnotationInstance annotation : excludeClasses) {
            processExcludeClass(eeModuleDescription, annotation, index);
        }
    }

    private void processInterceptors(final EEModuleDescription eeModuleDescription, final AnnotationInstance annotation, final CompositeIndex index) throws DeploymentUnitProcessingException {
        final AnnotationTarget target = annotation.target();
        if (target instanceof MethodInfo) {
            processMethodInterceptor(eeModuleDescription, MethodInfo.class.cast(target), annotation, index);
        } else if (target instanceof ClassInfo) {
            processClassInterceptor(eeModuleDescription, ClassInfo.class.cast(target), annotation, index);
        } else {
            throw new DeploymentUnitProcessingException("@Interceptors annotation is only allowed on methods and classes");
        }
    }

    private void processMethodInterceptor(final EEModuleDescription eeModuleDescription, final MethodInfo methodInfo, final AnnotationInstance annotation, final CompositeIndex index) {
        final Collection<ComponentDescription> components = this.getApplicableComponents(index, methodInfo.declaringClass(), eeModuleDescription);
        final AnnotationValue value = annotation.value();
        if (value != null) for (Type interceptorClass : value.asClassArray()) {
            for (ComponentDescription component : components) {
                component.addMethodInterceptor(methodIdentifierFromMethodInfo(methodInfo), new InterceptorDescription(interceptorClass.name().toString()));
            }
        }
    }

    private void processClassInterceptor(final EEModuleDescription eeModuleDescription, final ClassInfo classInfo, final AnnotationInstance annotation, final CompositeIndex index) {
        final Collection<ComponentDescription> components = this.getApplicableComponents(index, classInfo, eeModuleDescription);

        final AnnotationValue value = annotation.value();
        if (value != null) for (Type interceptorClass : value.asClassArray()) {
            for (ComponentDescription component : components) {
                component.addClassInterceptor(new InterceptorDescription(interceptorClass.name().toString()));
            }
        }
    }

    private void processExcludeDefault(final EEModuleDescription eeModuleDescription, final AnnotationInstance annotation, final CompositeIndex index) throws DeploymentUnitProcessingException {
        final AnnotationTarget target = annotation.target();
        if (target instanceof MethodInfo) {
            processMethodExcludeDefault(eeModuleDescription, MethodInfo.class.cast(target), index);
        } else if (target instanceof ClassInfo) {
            processClassExcludeDefault(eeModuleDescription, ClassInfo.class.cast(target), index);
        } else {
            throw new DeploymentUnitProcessingException("@ExcludeDefaultInterceptors annotation is only allowed on methods and classes");
        }
    }

    private void processClassExcludeDefault(EEModuleDescription eeModuleDescription, final ClassInfo classInfo, final CompositeIndex index) {
        final Collection<ComponentDescription> components = this.getApplicableComponents(index, classInfo, eeModuleDescription);
        for (ComponentDescription component : components) {
            component.setExcludeDefaultInterceptors(true);
        }
    }

    private void processMethodExcludeDefault(EEModuleDescription eeModuleDescription, MethodInfo methodInfo, final CompositeIndex index) {
        final Collection<ComponentDescription> components = this.getApplicableComponents(index, methodInfo.declaringClass(), eeModuleDescription);
        for (ComponentDescription component : components) {
            component.excludeDefaultInterceptors(methodIdentifierFromMethodInfo(methodInfo));
        }
    }

    private void processExcludeClass(final EEModuleDescription eeModuleDescription, final AnnotationInstance annotation, final CompositeIndex index) throws DeploymentUnitProcessingException {
        final AnnotationTarget target = annotation.target();
        if (target instanceof MethodInfo) {
            final MethodInfo methodInfo = MethodInfo.class.cast(target);
            final Collection<ComponentDescription> components = this.getApplicableComponents(index, methodInfo.declaringClass(), eeModuleDescription);
            for (ComponentDescription component : components) {
                component.excludeClassInterceptors(methodIdentifierFromMethodInfo(methodInfo));
            }
        } else {
            throw new DeploymentUnitProcessingException("@ExcludeDefaultInterceptors annotation is only allowed on methods");
        }
    }

    public void undeploy(DeploymentUnit context) {
    }

    private static MethodIdentifier methodIdentifierFromMethodInfo(MethodInfo methodInfo) {
        final String[] argTypes = new String[methodInfo.args().length];
        int i = 0;
        for (Type argType : methodInfo.args()) {
            argTypes[i++] = argType.name().toString();
        }
        return MethodIdentifier.getIdentifier(methodInfo.returnType().name().toString(), methodInfo.name(), argTypes);
    }

    /**
     * Returns the applicable components for the passed {@link ClassInfo klass}. If the passed <code>klass</code> represents
     * a component in the passed <code>eeModuleDescription</code>, then a collection containing only that {@link ComponentDescription component}
     * is returned. Else the passed <code>index</code> is used to find any known subclasses of the <code>klass</code> and then return a collection
     * of {@link ComponentDescription components} (if any), corresponding to those subclasses.
     * If there are no {@link ComponentDescription components} found for the passed <code>klass</code>, then this method returns an empty
     * collection.
     *
     * @param index               The {@link CompositeIndex}
     * @param klass               The {@link ClassInfo} for which {@link ComponentDescription components} are being queried
     * @param eeModuleDescription The {@link EEModuleDescription} to which the <code>klass</code> belongs
     * @return
     */
    private Collection<ComponentDescription> getApplicableComponents(final CompositeIndex index, final ClassInfo klass, final EEModuleDescription eeModuleDescription) {
        Set<ComponentDescription> componentDescriptions = new HashSet<ComponentDescription>();
        final List<ComponentDescription> descriptions = eeModuleDescription.getComponentsByClassName(klass.name().toString());
        if (!descriptions.isEmpty()) {
            componentDescriptions.addAll(descriptions);
        } else {
            componentDescriptions.addAll(this.getKnownSubClassComponents(index, klass, eeModuleDescription));
        }
        return componentDescriptions;
    }

    /**
     * Returns a collection of {@link ComponentDescription components} corresponding to each of the known subclasses of the
     * passed <code>superClass</code>. If a particular subclass isn't a component, then it is not added to the collection. A
     * subclass is considered as a component, if it is mapped as such in the passed <code>eeModuledescription</code>
     *
     * @param index               The {@link CompositeIndex}
     * @param superClass          The {@link ClassInfo} whose subclasses will be checked for {@link ComponentDescription components}
     * @param eeModuleDescription The {@link EEModuleDescription} to which the <code>superClass</code> belongs
     * @return
     */
    private Collection<ComponentDescription> getKnownSubClassComponents(final CompositeIndex index, final ClassInfo superClass, final EEModuleDescription eeModuleDescription) {
        Set<ClassInfo> subClasses = index.getAllKnownSubclasses(superClass.name());
        if (subClasses == null || subClasses.isEmpty()) {
            return Collections.emptySet();
        }
        Set<ComponentDescription> components = new HashSet<ComponentDescription>();
        for (ClassInfo subClass : subClasses) {
            final List<ComponentDescription> componentDescriptions = eeModuleDescription.getComponentsByClassName(subClass.name().toString());
            components.addAll(componentDescriptions);
        }
        return components;
    }

}
TOP

Related Classes of org.jboss.as.ee.component.deployers.InterceptorsAnnotationParsingProcessor

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.