Package org.apache.webbeans.xml

Source Code of org.apache.webbeans.xml.XMLDefinitionUtil

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with this
* work for additional information regarding copyright ownership. The ASF
* licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
* or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package org.apache.webbeans.xml;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.decorator.Decorator;
import javax.enterprise.context.NormalScope;
import javax.inject.Named;
import javax.inject.Scope;
import javax.enterprise.inject.NonBinding;
import javax.enterprise.inject.UnsatisfiedResolutionException;
import javax.enterprise.inject.deployment.DeploymentType;
import javax.enterprise.inject.deployment.Specializes;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.enterprise.inject.spi.Interceptor;
import javax.interceptor.AroundInvoke;

import org.apache.webbeans.WebBeansConstants;
import org.apache.webbeans.component.AbstractBean;
import org.apache.webbeans.component.xml.XMLManagedBean;
import org.apache.webbeans.component.xml.XMLProducerBean;
import org.apache.webbeans.container.InjectionResolver;
import org.apache.webbeans.decorator.WebBeansDecoratorConfig;
import org.apache.webbeans.event.NotificationManager;
import org.apache.webbeans.event.TransactionalObserverType;
import org.apache.webbeans.event.xml.BeanObserverXMLImpl;
import org.apache.webbeans.exception.WebBeansConfigurationException;
import org.apache.webbeans.exception.definition.NonexistentFieldException;
import org.apache.webbeans.exception.definition.NonexistentTypeException;
import org.apache.webbeans.inject.impl.InjectionPointFactory;
import org.apache.webbeans.inject.xml.XMLInjectionModelType;
import org.apache.webbeans.inject.xml.XMLInjectionPointModel;
import org.apache.webbeans.intercept.InterceptorData;
import org.apache.webbeans.intercept.InterceptorUtil;
import org.apache.webbeans.intercept.WebBeansInterceptorConfig;
import org.apache.webbeans.intercept.webbeans.WebBeansInterceptor;
import org.apache.webbeans.proxy.JavassistProxyFactory;
import org.apache.webbeans.util.AnnotationUtil;
import org.apache.webbeans.util.Asserts;
import org.apache.webbeans.util.ClassUtil;
import org.apache.webbeans.util.WebBeansUtil;
import org.dom4j.Element;

@SuppressWarnings("unchecked")
public final class XMLDefinitionUtil
{
    private XMLDefinitionUtil()
    {

    }

    /**
     * Checks the conditions for simple webbeans class defined in the XML file.
     *
     * @param clazz simple webbeans class declared in XML
     * @throws WebBeansConfigurationException if check is fail
     */
    public static void checkSimpleWebBeansInXML(Class<?> clazz, Element webBeanDecleration, String errorMessage) throws WebBeansConfigurationException
    {
        Asserts.nullCheckForClass(clazz);
        if (errorMessage == null)
        {
            errorMessage = "XML defined simple webbeans failed. ";
        }

        int modifier = clazz.getModifiers();

        if (ClassUtil.isDefinitionConstainsTypeVariables(clazz))
        {
            throw new WebBeansConfigurationException(errorMessage + "Simple WebBeans component implementation class : " + clazz.getName() + " can not be parametrized type");
        }

        if (!ClassUtil.isStatic(modifier) && ClassUtil.isInnerClazz(clazz))
        {
            throw new WebBeansConfigurationException(errorMessage + "Simple WebBeans component implementation class : " + clazz.getName() + " can not be non-static inner class");
        }

        if (clazz.isAnnotationPresent(javax.interceptor.Interceptor.class))
        {
            boolean found = XMLUtil.isElementChildExistWithWebBeansNameSpace(webBeanDecleration, WebBeansConstants.WEB_BEANS_XML_INTERCEPTOR_ELEMENT);
            if (!found)
            {
                throw new WebBeansConfigurationException(errorMessage + "Simple WebBeans component implementation class : " + clazz.getName() + " must be declared as <Interceptor> element in the XML");
            }
        }

        if (clazz.isAnnotationPresent(Decorator.class))
        {
            boolean found = XMLUtil.isElementChildExistWithWebBeansNameSpace(webBeanDecleration, WebBeansConstants.WEB_BEANS_XML_DECORATOR_ELEMENT);
            if (!found)
            {
                throw new WebBeansConfigurationException(errorMessage + "Simple WebBeans component implementation class : " + clazz.getName() + " must be declared as <Decorator> element in the XML");
            }
        }

    }

    public static void checkTypeMetaDataClasses(List<Class<? extends Annotation>> typeSet, String errorMessage)
    {
        if (typeSet != null && !typeSet.isEmpty())
        {
            Iterator<Class<? extends Annotation>> it = typeSet.iterator();
            while (it.hasNext())
            {
                Class<? extends Annotation> clazz = it.next();
                if (clazz.isAnnotationPresent(DeploymentType.class)
                        || clazz.isAnnotationPresent(NormalScope.class)
                        || clazz.isAnnotationPresent(Scope.class)
                        || AnnotationUtil.isQualifierAnnotation(clazz)
                        || AnnotationUtil.isInterceptorBindingAnnotation(clazz)
                        || AnnotationUtil.isStereoTypeAnnotation(clazz)
                        || clazz.equals(Named.class)
                        || clazz.equals(Specializes.class) || clazz.equals(javax.interceptor.Interceptor.class)
                        || clazz.equals(Decorator.class))
                {
                    continue;
                }
                else
                {
                    throw new WebBeansConfigurationException(errorMessage + " TypeLevelMeta data configuration is failed because of the class : " + clazz.getName() + " is not applicable type");
                }
            }
        }

    }

    /**
     * Gets applicable annotation class for given defineType parameter from the
     * given annotation set.
     *
     * @param component webbeans component
     * @param annotationSet type-level metadata annotation set
     * @param defineType annotation type class
     * @param errorMessage error message for the operation
     * @return applicable annotation class for given defineType parameter from
     *         the given set
     */
    public static <T> Class<? extends Annotation> defineXMLTypeMetaData(AbstractBean<T> component, List<Class<? extends Annotation>> annotationSet, Class<? extends Annotation> defineType, String errorMessage)
    {
        // Found annotation for given defineType parameter
        Class<? extends Annotation> metaType = null;

        Iterator<Class<? extends Annotation>> it = annotationSet.iterator();
        boolean found = false;
        while (it.hasNext())
        {
            Class<? extends Annotation> temp = it.next();
            if (temp.isAnnotationPresent(defineType))
            {
                if (found)
                {
                    throw new WebBeansConfigurationException(errorMessage);
                }
                else
                {
                    metaType = temp;
                    found = true;
                }
            }
        }

        return metaType;
    }

    public static <T> boolean defineXMLBindingType(AbstractBean<T> component, List<Class<? extends Annotation>> annotationSet, List<Element> annotationElementList, String errorMessage)
    {
        Iterator<Class<? extends Annotation>> it = annotationSet.iterator();
        boolean found = false;
        int i = 0;
        while (it.hasNext())
        {
            Class<? extends Annotation> temp = it.next();
            if (AnnotationUtil.isQualifierAnnotation(temp))
            {
                Method[] methods = temp.getDeclaredMethods();

                for (Method method : methods)
                {
                    Class<?> clazz = method.getReturnType();
                    if (clazz.isArray() || clazz.isAnnotation())
                    {
                        if (!AnnotationUtil.isAnnotationExist(method.getAnnotations(), NonBinding.class))
                        {
                            throw new WebBeansConfigurationException(errorMessage + "WebBeans definition class : " + component.getReturnType().getName() + " @Qualifier : " + temp.getName() + " must have @NonBinding valued members for its array-valued and annotation valued members");
                        }
                    }
                }

                if (!found)
                {
                    found = true;
                }

                component.addQualifier(XMLUtil.getXMLDefinedAnnotationMember(annotationElementList.get(i), temp, errorMessage));
            }

            i++;
        }

        return found;
    }

    public static <T> void defineXMLClassLevelInterceptorType(XMLManagedBean<T> component, List<Class<? extends Annotation>> annotationSet, List<Element> annotationElementList, String errorMessage)
    {
        Iterator<Class<? extends Annotation>> it = annotationSet.iterator();

        Set<Annotation> bindingTypeSet = new HashSet<Annotation>();
        int i = 0;
        while (it.hasNext())
        {
            Class<? extends Annotation> temp = it.next();
            if (AnnotationUtil.isInterceptorBindingAnnotation(temp))
            {
                bindingTypeSet.add(XMLUtil.getXMLDefinedAnnotationMember(annotationElementList.get(i), temp, errorMessage));
            }

            i++;
        }

        Set<Annotation> stereoTypesSet = component.getOwbStereotypes();
        Annotation[] stereoTypes = new Annotation[stereoTypesSet.size()];
        stereoTypes = stereoTypesSet.toArray(stereoTypes);
        for (Annotation stero : stereoTypes)
        {
            if (AnnotationUtil.isInterceptorBindingMetaAnnotationExist(stero.annotationType().getDeclaredAnnotations()))
            {
                Annotation[] steroInterceptorBindings = AnnotationUtil.getInterceptorBindingMetaAnnotations(stero.annotationType().getDeclaredAnnotations());

                for (Annotation ann : steroInterceptorBindings)
                {
                    bindingTypeSet.add(ann);
                }
            }
        }

        Annotation[] anns = new Annotation[bindingTypeSet.size()];
        anns = bindingTypeSet.toArray(anns);

        Set<Interceptor<?>> set = WebBeansInterceptorConfig.findDeployedWebBeansInterceptor(anns);

        WebBeansInterceptorConfig.addComponentInterceptors(set, component.getInterceptorStack());

    }

    public static <T> void defineXMLMethodLevelInterceptorType(XMLManagedBean<T> component, Method interceptorMethod, Element interceptorMethodElement, String errorMessage)
    {
        List<Element> bindingTypes = interceptorMethodElement.elements();
        Set<Annotation> bindingTypesSet = new HashSet<Annotation>();
        for (Element bindingType : bindingTypes)
        {
            Class<? extends Annotation> annot = (Class<? extends Annotation>) XMLUtil.getElementJavaType(bindingType);
            Annotation bindingAnnot = XMLUtil.getXMLDefinedAnnotationMember(bindingType, annot, errorMessage);

            bindingTypesSet.add(bindingAnnot);
        }

        Annotation[] result = new Annotation[bindingTypesSet.size()];
        result = bindingTypesSet.toArray(result);

        Set<Interceptor<?>> setInterceptors = WebBeansInterceptorConfig.findDeployedWebBeansInterceptor(result);
        Iterator<Interceptor<?>> it = setInterceptors.iterator();

        List<InterceptorData> stack = component.getInterceptorStack();
        while (it.hasNext())
        {
            WebBeansInterceptor interceptor = (WebBeansInterceptor) it.next();

            WebBeansUtil.configureInterceptorMethods(interceptor, interceptor.getClazz(), AroundInvoke.class, false, true, stack, interceptorMethod, true);
            WebBeansUtil.configureInterceptorMethods(interceptor, interceptor.getClazz(), PostConstruct.class, false, true, stack, interceptorMethod, true);
            WebBeansUtil.configureInterceptorMethods(interceptor, interceptor.getClazz(), PreDestroy.class, false, true, stack, interceptorMethod, true);
        }

    }

    /**
     * Configures the webbeans component stereotype.
     *
     * @param component webbeans component
     * @param annotationSet set of type-level metadata annotation set
     */
    public static <T> void defineXMLStereoType(AbstractBean<T> component, List<Class<? extends Annotation>> annotationSet)
    {
        Iterator<Class<? extends Annotation>> it = annotationSet.iterator();
        while (it.hasNext())
        {
            Class<? extends Annotation> temp = it.next();
            if (AnnotationUtil.isStereoTypeAnnotation(temp))
            {
                component.addStereoType(JavassistProxyFactory.createNewAnnotationProxy(temp));
            }
        }
    }

    public static <T> boolean defineXMLName(AbstractBean<T> component, List<Class<? extends Annotation>> annotationSet)
    {
        Iterator<Class<? extends Annotation>> it = annotationSet.iterator();
        while (it.hasNext())
        {
            Class<? extends Annotation> temp = it.next();
            if (temp.equals(Named.class))
            {
                return true;
            }
        }

        return false;
    }

    public static <T> void defineXMLSpecializes(XMLManagedBean<T> component, List<Class<? extends Annotation>> annotationSet)
    {
        Iterator<Class<? extends Annotation>> it = annotationSet.iterator();
        while (it.hasNext())
        {
            Class<? extends Annotation> temp = it.next();
            if (temp.equals(Specializes.class))
            {
                XMLSpecializesManager.getInstance().addXMLSpecializeClass(temp);
            }
        }
    }

    public static <T> void defineXMLInterceptors(XMLManagedBean<T> component, List<Class<? extends Annotation>> annotationSet, List<Element> annotationElementList, String errorMessage)
    {
        Iterator<Class<? extends Annotation>> it = annotationSet.iterator();
        boolean found = false;

        Set<Annotation> interceptorBindingTypes = new HashSet<Annotation>();
        int i = 0;
        while (it.hasNext())
        {
            Class<? extends Annotation> temp = it.next();
            if (temp.equals(javax.interceptor.Interceptor.class))
            {
                if (found)
                {
                    throw new WebBeansConfigurationException(errorMessage + "More than one <Interceptor> element exist for class : " + component.getReturnType().getName());
                }
                else
                {
                    found = true;
                }
            }
            else if (AnnotationUtil.isInterceptorBindingAnnotation(temp))
            {
                Element annotationElement = annotationElementList.get(i);
                Annotation bindingAnnotation = XMLUtil.getXMLDefinedAnnotationMember(annotationElement, temp, errorMessage);
                interceptorBindingTypes.add(bindingAnnotation);
            }

            i++;
        }

        if (interceptorBindingTypes.size() == 0)
        {
            throw new WebBeansConfigurationException(errorMessage + "<Interceptor> decleration must have one interceptor binding type for class : " + component.getReturnType().getName());
        }

        Annotation[] anns = new Annotation[interceptorBindingTypes.size()];
        anns = interceptorBindingTypes.toArray(anns);
        InterceptorUtil.checkLifecycleConditions(component.getReturnType(), anns, errorMessage + "Lifecycle interceptor : " + component.getReturnType().getName() + " interceptor binding type must be defined as @Target{TYPE}");

        WebBeansInterceptorConfig.configureInterceptorClass((XMLManagedBean<Object>) component, anns);
    }

    public static <T> void defineXMLDecorators(XMLManagedBean<T> component, List<Class<? extends Annotation>> annotationSet, Element decoratorDecleration, String errorMessage)
    {
        Iterator<Class<? extends Annotation>> it = annotationSet.iterator();
        boolean found = false;
        while (it.hasNext())
        {
            Class<? extends Annotation> temp = it.next();
            if (temp.equals(Decorator.class))
            {
                if (found)
                {
                    throw new WebBeansConfigurationException(errorMessage + "More than one <Decorator> element exist");
                }
                else
                {
                    found = true;
                }
            }
        }

        if (found)
        {
            List<Element> childs = decoratorDecleration.elements();
            for (Element child : childs)
            {
                if (XMLUtil.getElementNameSpace(child).equals(XMLUtil.getElementNameSpace(decoratorDecleration)) && XMLUtil.isElementHasDecoratesChild(child))
                {
                    Field field = ClassUtil.getFieldWithName(component.getReturnType(), child.getName());
                    if (field == null)
                    {
                        throw new NonexistentFieldException(errorMessage + "Field with name : " + child.getName() + " not found in the decorator class : " + component.getReturnType().getName());
                    }

                    Element decorates = child.element(WebBeansConstants.WEB_BEANS_XML_DECORATES_ELEMENT);
                    Element type = (Element) decorates.elements().get(0);

                    Class<?> apType = XMLUtil.getElementJavaType(type);

                    if (!field.getType().isAssignableFrom(apType))
                    {
                        throw new WebBeansConfigurationException(errorMessage + "Field name : " + field.getName() + " xml defined class type must be assignable to the field actual class type");
                    }

                    XMLInjectionPointModel model = XMLUtil.getInjectionPointModel(type, errorMessage);

                    WebBeansDecoratorConfig.configureXMLDecoratorClass((AbstractBean<Object>) component, model);
                }
                else
                {
                    throw new WebBeansConfigurationException(errorMessage + "Delegate decleration must defined exactly one child element with name Decorates");
                }
            }
        }
    }

    /**
     * Returns newly created and configures xml webbeans producer component.
     *
     * @param component webbeans component that defines producer method
     * @param producesMethod producer method
     * @param producerMethodElement produce method xml element
     * @param errorMessage error message
     * @return newly created and configures xml webbeans producer component.
     * @see XMLProducerBean
     */
    public static <T> XMLProducerBean<T> defineXMLProducerMethod(WebBeansXMLConfigurator configurator, XMLManagedBean<T> component, Method producesMethod, Element producerMethodElement, String errorMessage)
    {
        boolean producesDefined = false;
        List<Element> childElements = producerMethodElement.elements();
        Class<T> type = null;
        Element typeElement = null;
        Element arrayElement = null;
        List<Class<? extends Annotation>> memberLevelMetaData = new ArrayList<Class<? extends Annotation>>();
        List<Element> memberLevelElement = new ArrayList<Element>();
        List<XMLInjectionPointModel> injectedParameters = new ArrayList<XMLInjectionPointModel>();

        for (Element childElement : childElements)
        {
            if (XMLUtil.isElementInWebBeansNameSpaceWithName(childElement, WebBeansConstants.WEB_BEANS_XML_PRODUCES_ELEMENT))
            {
                if (producesDefined == false)
                {
                    producesDefined = true;
                }
                else
                {
                    throw new WebBeansConfigurationException(errorMessage + "More than one <Produces> element is defined");
                }

                List<Element> producesElementChilds = childElement.elements();
                boolean definedType = false;

                for (Element producesElementChild : producesElementChilds)
                {
                    if (producesElementChild.getName().equals(WebBeansConstants.WEB_BEANS_XML_ARRAY_ELEMENT))
                    {
                        arrayElement = producesElementChild;
                        definedType = true;
                    }
                    else
                    {
                        type = (Class<T>) XMLUtil.getElementJavaType(producesElementChild);
                        if (type == null)
                        {
                            throw new NonexistentTypeException(errorMessage + "Java type : " + XMLUtil.getElementJavaClassName(producesElementChild) + " does not exist in the <Produces> element child");
                        }

                        else if (type.isAnnotation())
                        {
                            memberLevelMetaData.add((Class<? extends Annotation>) type);
                            memberLevelElement.add(producesElementChild);
                        }
                        else
                        {
                            if (!type.isAssignableFrom(producesMethod.getReturnType()) && !producesMethod.getReturnType().isAssignableFrom(type))
                            {
                                throw new WebBeansConfigurationException(errorMessage + "Defined returned method type is not compatible for producer method name : " + producesMethod.getName() + " in class : " + component.getReturnType().getName());
                            }

                            if (definedType)
                            {
                                throw new WebBeansConfigurationException(errorMessage + "More than one Java type in the <Produces> element");
                            }
                            else
                            {
                                typeElement = producesElementChild;
                                definedType = true;
                            }
                        }
                    }
                }

                if (!definedType)
                {
                    throw new WebBeansConfigurationException(errorMessage + "<Produces> element must define at least one java type child");
                }
            }
            else
            {
                XMLInjectionPointModel injectionPointModel = XMLUtil.getInjectionPointModel(childElement, errorMessage);
                injectedParameters.add(injectionPointModel);

            }
        }

        XMLProducerBean<T> producerComponentImpl = configureProducerMethod(component, producesMethod, injectedParameters, type, arrayElement, typeElement, errorMessage);

        configureProducerTypeLevelMetaData(configurator, producerComponentImpl, producesMethod, producerMethodElement, memberLevelMetaData, memberLevelElement, component, errorMessage);

        return producerComponentImpl;
    }

    /**
     * Configures and returns the newly created producer method webbeans
     * component.
     *
     * @param parentComponent producer method webbeans parent component
     * @param producesMethod producer method
     * @param injectedParameters injected parameters of the producer method
     * @param type java class type of the producer method return type, null if
     *            the return type is defined as an Array element.
     * @param arrayElement if the return type is array type, this parameter is
     *            the Array element definition
     * @param typeElement if the return type is a Java type, this parameter is
     *            the Java type element
     * @param errorMessage error message
     * @return new xml defines producer method component
     * @see XMLProducerBean
     */
    private static <T> XMLProducerBean<T> configureProducerMethod(AbstractBean<?> parentComponent, Method producesMethod, List<XMLInjectionPointModel> injectedParameters, Class<T> type, Element arrayElement, Element typeElement, String errorMessage)
    {
        /* New producer webbeans component */
        XMLProducerBean<T> producerComponentImpl = new XMLProducerBean<T>(parentComponent, type);

        /* Check return type is the array type */
        if (arrayElement != null)
        {
            /* Configures array type */
            XMLUtil.defineXMLProducerApiTypeFromArrayElement(producerComponentImpl, arrayElement, errorMessage);
        }
        /* Return type is java type */
        else
        {
            /* Configures the java api types and actual type parameters */
            XMLInjectionPointModel model = XMLUtil.getInjectionPointModel(typeElement, errorMessage);

            producerComponentImpl.setActualTypeArguments(model.getActualTypeArguments());
            producerComponentImpl.addApiType(model.getInjectionClassType());

            if (model.getInjectionClassType().isPrimitive())
            {
                producerComponentImpl.setNullable(false);
            }
        }

        producerComponentImpl.addApiType(Object.class);

        /* Set creator method */
        producerComponentImpl.setCreatorMethod(producesMethod);

        /* Configures producer method injected parameters */
        for (XMLInjectionPointModel injectionPointModel : injectedParameters)
        {
            producerComponentImpl.addProducerMethodInjectionPointModel(injectionPointModel);           
            producerComponentImpl.addInjectionPoint(getXMLMethodInjectionPoint(producerComponentImpl, injectionPointModel, producesMethod));
        }

        return producerComponentImpl;

    }

    /**
     * Configures xml defined producer method webbeans type level metadatas.
     *
     * @param producerComponentImpl xml webbeans producer component
     * @param producesMethod producer method
     * @param producerMethodElement producer method xml element
     * @param memberLevelMetaData member level annotations
     * @param memberLevelElement member level xml elements
     * @param component parent component that defines producer method
     * @param errorMessage error message
     * @return type level metadata configured webbeans
     * @see XMLProducerBean
     */
    private static <T> XMLProducerBean<T> configureProducerTypeLevelMetaData(WebBeansXMLConfigurator configurator, XMLProducerBean<T> producerComponentImpl, Method producesMethod, Element producerMethodElement, List<Class<? extends Annotation>> memberLevelMetaData, List<Element> memberLevelElement, XMLManagedBean<T> component, String errorMessage)
    {

        for (Class<? extends Annotation> memberLevelMetaDataClass : memberLevelMetaData)
        {
            if (!memberLevelMetaDataClass.isAnnotationPresent(DeploymentType.class) && !memberLevelMetaDataClass.isAnnotationPresent(NormalScope.class) && !AnnotationUtil.isStereoTypeAnnotation(memberLevelMetaDataClass) && !memberLevelMetaDataClass.equals(Named.class))
            {
                throw new WebBeansConfigurationException(errorMessage + "Defined annotations for producer method name : " + producesMethod.getName() + " in class : " + component.getReturnType().getName() + " is not correct");
            }
        }

        configurator.configureProducerTypeLevelMetaData(producerComponentImpl, memberLevelMetaData, memberLevelElement, producerMethodElement);

        return producerComponentImpl;
    }

    /**
     * Configures the disposal method of the webbeans component using the xml
     * configuration.
     *
     * @param component producer method webbeans component
     * @param disposalMethod disposal method defined in the xml
     * @param disposalMethodElement disposal method xml element
     * @param errorMessage error message used in exceptions
     * @throws WebBeansConfigurationException if more than one Disposal element
     *             exist for the given disposal method element
     * @throws UnsatisfiedResolutionException if no producer method found for
     *             given disposal method
     */
    public static <T> void defineXMLDisposalMethod(XMLManagedBean<T> component, Method disposalMethod, Element disposalMethodElement, String errorMessage)
    {
        /* Disposal method element childs */
        List<Element> disposalChildElements = disposalMethodElement.elements();

        /* Multiple <Disposes> element control parameter */
        boolean disposalDefined = false;

        /* Other parameter elements other than @Disposes */
        List<Element> otherParameterElements = new ArrayList<Element>();

        XMLProducerBean<?> producerComponent = null;

        for (Element childElement : disposalChildElements)
        {
            if (XMLUtil.isElementInWebBeansNameSpaceWithName(childElement, WebBeansConstants.WEB_BEANS_XML_DISPOSES_ELEMENT))
            {
                if (disposalDefined == false)
                {
                    disposalDefined = true;
                }
                else
                {
                    throw new WebBeansConfigurationException(errorMessage + "More than one <Disposal> element is defined for defining disposal method : " + disposalMethod.getName());
                }

                Element typeElement = (Element) childElement.elements().get(0);

                /* Find disposal method model */
                XMLInjectionPointModel model = XMLUtil.getInjectionPointModel(typeElement, errorMessage);
               
                component.addInjectionPoint(getXMLMethodInjectionPoint(component, model, disposalMethod));

                /* Binding types for disposal method */
                Set<Annotation> bindingTypes = model.getBindingTypes();
                Annotation[] bindingAnns = new Annotation[bindingTypes.size()];
                bindingAnns = bindingTypes.toArray(bindingAnns);

                Set<Bean<?>> set = InjectionResolver.getInstance().implResolveByType(model.getInjectionGenericType(), bindingAnns);
                producerComponent = (XMLProducerBean<?>) set.iterator().next();

                if (producerComponent == null)
                {
                    throw new UnsatisfiedResolutionException(errorMessage + "Producer method component of the disposal method : " + disposalMethod.getName() + "is not found");
                }

                producerComponent.setDisposalMethod(disposalMethod);

            }
            /* Disposal method parameter other than @Disposes */
            else
            {
                otherParameterElements.add(childElement);
            }
        }// end of for childs

        /* Add other params injection point models */
        for (Element otherElement : otherParameterElements)
        {
            XMLInjectionPointModel injectionPointParamModel = XMLUtil.getInjectionPointModel(otherElement, errorMessage);
            producerComponent.addDisposalMethodInjectionPointModel(injectionPointParamModel);
        }
    }

    public static <T, K> void defineXMLObservesMethod(XMLManagedBean<T> component, Method observesMethod, Element observesMethodElement, String errorMessage)
    {
        component.addObservableMethod(observesMethod);

        /* Observes method element childs */
        List<Element> observesChildElements = observesMethodElement.elements();

        /* Other parameter elements other than @Observes */
        List<Element> otherParameterElements = new ArrayList<Element>();

        BeanObserverXMLImpl<K> beanObserver = new BeanObserverXMLImpl<K>(component, observesMethod, false, TransactionalObserverType.NONE);

        Class<K> eventType = null;

        for (Element childElement : observesChildElements)
        {
            if (XMLUtil.isElementInWebBeansNameSpaceWithName(childElement, WebBeansConstants.WEB_BEANS_XML_OBSERVES_ELEMENT))
            {
                Element typeElement = (Element) childElement.elements().get(0);

                eventType = (Class<K>) XMLUtil.getElementJavaType(typeElement);

                /* Find observes method model */
                XMLInjectionPointModel model = XMLUtil.getInjectionPointModel(typeElement, errorMessage);
               
                component.addInjectionPoint(getXMLMethodInjectionPoint(component, model, observesMethod));

                /* Binding types for disposal method */
                Set<Annotation> bindingTypes = model.getBindingTypes();
                Annotation[] bindingAnns = new Annotation[bindingTypes.size()];
                bindingAnns = bindingTypes.toArray(bindingAnns);

                beanObserver.addXMLInjectionObservesParameter(model);

                NotificationManager.getInstance().addObserver(beanObserver, eventType, bindingAnns);

            }
            /* Disposal method parameter other than @Disposes */
            else
            {
                otherParameterElements.add(childElement);
            }
        }// end of for childs

        /* Add other params injection point models */
        for (Element otherElement : otherParameterElements)
        {
            XMLInjectionPointModel injectionPointParamModel = XMLUtil.getInjectionPointModel(otherElement, errorMessage);
            beanObserver.addXMLInjectionObservesParameter(injectionPointParamModel);
        }
    }
   
    public static InjectionPoint getXMLMethodInjectionPoint(AbstractBean<?> component, XMLInjectionPointModel model, Method method)
    {
        Asserts.assertNotNull(model,"model parameter can not be null");
        Asserts.assertNotNull(method,"method parameter can not be null");
       
        Annotation[] annots = method.getAnnotations();
        for(Annotation annotation : annots)
        {
            model.addAnnotation(annotation);
        }
       
        model.setInjectionMember(method);
        model.setType(XMLInjectionModelType.METHOD);
       
        return InjectionPointFactory.getXMLInjectionPointData(component, model);
       
    }
}
TOP

Related Classes of org.apache.webbeans.xml.XMLDefinitionUtil

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.