Package org.apache.myfaces.extensions.cdi.core.impl.util

Source Code of org.apache.myfaces.extensions.cdi.core.impl.util.CodiUtils

/*
* 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.myfaces.extensions.cdi.core.impl.util;

import org.apache.myfaces.extensions.cdi.core.api.Advanced;
import org.apache.myfaces.extensions.cdi.core.api.config.CodiCoreConfig;
import org.apache.myfaces.extensions.cdi.core.api.projectstage.ProjectStage;
import org.apache.myfaces.extensions.cdi.core.api.provider.BeanManagerProvider;
import org.apache.myfaces.extensions.cdi.core.api.util.ClassUtils;
import static org.apache.myfaces.extensions.cdi.core.api.util.ClassUtils.tryToInstantiateClassForName;

import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.InjectionTarget;
import javax.enterprise.util.Nonbinding;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import java.util.Set;

/**
* This is a collection of a few useful static helper functions.
* <p/>
*/
public class CodiUtils
{
    private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];

    public static <T> T createNewInstanceOfBean(CreationalContext<T> creationalContext, Bean<T> bean)
    {
        return createNewInstanceOfBean(bean, creationalContext);
    }

    public static <T> T createNewInstanceOfBean(Bean<T> bean, CreationalContext<T> creationalContext)
    {
        return bean.create(creationalContext);
    }

    public static <T> T getOrCreateScopedInstanceOfBeanByName(
            BeanManager beanManager, String beanName, Class<T> targetClass)
    {
        Set<Bean<?>> foundBeans = beanManager.getBeans(beanName);

        Bean<?> bean = beanManager.resolve(foundBeans);

        //noinspection unchecked
        return (T) getContextualReference(beanManager, targetClass, bean);
    }

    public static <T> Bean<T> getOrCreateBeanByClass(Class<T> targetClass, Annotation... qualifier)
    {
        return getOrCreateBeanByClass(BeanManagerProvider.getInstance().getBeanManager(), targetClass, qualifier);
    }

    public static <T> Bean<T> getOrCreateBeanByClass(
            BeanManager beanManager, Class<T> targetClass, Annotation... qualifier)
    {
        return getOrCreateBeanByClass(beanManager, targetClass, false, qualifier);
    }

    public static <T> Bean<T> getOrCreateBeanByClass(BeanManager beanManager, Class<T> targetClass,
                                                     boolean optionalBeanAllowed, Annotation... qualifier)
    {
        Set<? extends Bean> foundBeans = beanManager.getBeans(targetClass, qualifier);

        if(foundBeans.size() >= 1)
        {
            return (Bean<T>) beanManager.resolve((Set<Bean<? extends Object>>) foundBeans);
        }

        if(!optionalBeanAllowed)
        {
            throw new IllegalStateException("No bean found for type: " + targetClass.getName());
        }
        return null;
    }

    public static <T> T getContextualReferenceByClass(Class<T> targetClass, Annotation... qualifier)
    {
        return getContextualReferenceByClass(BeanManagerProvider.getInstance().getBeanManager(),
                targetClass, qualifier);
    }

    public static <T> T getContextualReferenceByClass(
            BeanManager beanManager, Class<T> targetClass, Annotation... qualifier)
    {
        return getContextualReferenceByClass(beanManager, targetClass, false, qualifier);
    }

    public static <T> T getContextualReferenceByClass(
            Class<T> targetClass, boolean optionalBeanAllowed, Annotation... qualifier)
    {
        return getContextualReferenceByClass(BeanManagerProvider.getInstance().getBeanManager(),
                targetClass, optionalBeanAllowed, qualifier);
    }

    public static <T> T getContextualReferenceByClass(
            BeanManager beanManager, Class<T> targetClass, boolean optionalBeanAllowed, Annotation... qualifier)
    {
        Bean<?> foundBean = getOrCreateBeanByClass(beanManager, targetClass, optionalBeanAllowed, qualifier);

        if(foundBean != null)
        {
            //noinspection unchecked
            return (T) getContextualReference(beanManager, targetClass, foundBean);
        }
        return null;
    }

    public static <T> T getContextualReference(BeanManager beanManager, Type t, Bean<T> bean)
    {
        CreationalContext<T> cc = beanManager.createCreationalContext(bean);
        return  (T) beanManager.getReference(bean, t, cc);
    }

    private static <T> CreationalContext<T> getCreationalContextFor(BeanManager beanManager, Bean<T> bean)
    {
        return beanManager.createCreationalContext(bean);
    }

    /**
     * Load Properties from a configuration file with the given resourceName.
     *
     * @param resourceName
     * @return Properties or <code>null</code> if the given property file doesn't exist
     * @throws IOException on underlying IO problems
     */
    public static Properties getProperties(String resourceName) throws IOException
    {
        Properties props = null;
        ClassLoader cl = ClassUtils.getClassLoader(resourceName);
        InputStream is = cl.getResourceAsStream(resourceName);
        if (is != null)
        {
            props = new Properties();
            props.load(is);
        }

        return props;
    }

    public static ProjectStage getCurrentProjectStage()
    {
        return getContextualReferenceByClass(ProjectStage.class);
    }

    public static <T> T injectFields(T instance)
    {
        CodiCoreConfig codiCoreConfig = getContextualReferenceByClass(CodiCoreConfig.class);

        return injectFields(instance, codiCoreConfig.isAdvancedQualifierRequiredForDependencyInjection());
    }

    public static <T> T injectFields(T instance, boolean requiresAdvancedQualifier)
    {
        if(instance == null)
        {
            return null;
        }

        if(requiresAdvancedQualifier && instance.getClass().isAnnotationPresent(Advanced.class))
        {
            return tryToInjectFields(instance);
        }
        else if(!requiresAdvancedQualifier)
        {
            return tryToInjectFields(instance);
        }
        return instance;
    }

    /**
     * Performes dependency injection for objects which aren't know as bean
     *
     * @param instance the target instance
     * @param <T> generic type
     * @return an instance produced by the {@link javax.enterprise.inject.spi.BeanManager} or
     * a manually injected instance (or null if the given instance is null)
     */
    @SuppressWarnings({"unchecked"})
    private static <T> T tryToInjectFields(T instance)
    {
        BeanManager beanManager = BeanManagerProvider.getInstance().getBeanManager();

        T foundBean = (T) getContextualReferenceByClass(beanManager, instance.getClass(), true);

        if(foundBean != null)
        {
            return foundBean;
        }

        CreationalContext creationalContext = beanManager.createCreationalContext(null);

        AnnotatedType annotatedType = beanManager.createAnnotatedType(instance.getClass());
        InjectionTarget injectionTarget = beanManager.createInjectionTarget(annotatedType);
        injectionTarget.inject(instance, creationalContext);
        return instance;
    }

    /**
     * Checks if the given qualifiers are equal.
     *
     * Qualifiers are equal if they have the same annotationType and all their
     * methods, except those annotated with @Nonbinding, return the same value.
     *
     * @param qualifier1
     * @param qualifier2
     * @return
     */
    public static boolean isQualifierEqual(Annotation qualifier1, Annotation qualifier2)
    {
        Class<? extends Annotation> qualifier1AnnotationType = qualifier1.annotationType();

        // check if the annotationTypes are equal
        if (qualifier1AnnotationType == null || !qualifier1AnnotationType.equals(qualifier2.annotationType()))
        {
            return false;
        }

        // check the values of all qualifier-methods
        // except those annotated with @Nonbinding
        List<Method> bindingQualifierMethods = getBindingQualifierMethods(qualifier1AnnotationType);

        for (Method method : bindingQualifierMethods)
        {
            Object value1 = callMethod(qualifier1, method);
            Object value2 = callMethod(qualifier2, method);

            if (!checkEquality(value1, value2))
            {
                return false;
            }
        }

        return true;
    }

    /**
     * Quecks if the two values are equal.
     *
     * @param value1
     * @param value2
     * @return
     */
    private static boolean checkEquality(Object value1, Object value2)
    {
        if ((value1 == null && value2 != null) || (value1 != null && value2 == null))
        {
            return false;
        }

        if (value1 == null && value2 == null)
        {
            return true;
        }

        // now both values are != null

        Class<?> valueClass = value1.getClass();
       
        if (!valueClass.equals(value2.getClass()))
        {
            return false;
        }

        if (valueClass.isPrimitive())
        {
            // primitive types can be checked with ==
            return value1 == value2;
        }
        else if (valueClass.isArray())
        {
            Class<?> arrayType = valueClass.getComponentType();

            if (arrayType.isPrimitive())
            {
                if (Long.TYPE == arrayType)
                {
                    return Arrays.equals(((long[]) value1), (long[]) value2);
                }
                else if (Integer.TYPE == arrayType)
                {
                    return Arrays.equals(((int[]) value1), (int[]) value2);
                }
                else if (Short.TYPE == arrayType)
                {
                    return Arrays.equals(((short[]) value1), (short[]) value2);
                }
                else if (Double.TYPE == arrayType)
                {
                    return Arrays.equals(((double[]) value1), (double[]) value2);
                }
                else if (Float.TYPE == arrayType)
                {
                    return Arrays.equals(((float[]) value1), (float[]) value2);
                }
                else if (Boolean.TYPE == arrayType)
                {
                    return Arrays.equals(((boolean[]) value1), (boolean[]) value2);
                }
                else if (Byte.TYPE == arrayType)
                {
                    return Arrays.equals(((byte[]) value1), (byte[]) value2);
                }
                else if (Character.TYPE == arrayType)
                {
                    return Arrays.equals(((char[]) value1), (char[]) value2);
                }
                return false;
            }
            else
            {
                return Arrays.equals(((Object[]) value1), (Object[]) value2);
            }
        }
        else
        {
            return value1.equals(value2);
        }
    }

    /**
     * Calls the given method on the given instance.
     * Used to determine the values of annotation instances.
     *
     * @param instance
     * @param method
     * @return
     */
    private static Object callMethod(Object instance, Method method)
    {
        boolean accessible = method.isAccessible();

        try
        {
            if (!accessible)
            {
                method.setAccessible(true);
            }

            return method.invoke(instance, EMPTY_OBJECT_ARRAY);
        }
        catch (Exception e)
        {
            throw new RuntimeException("Exception in method call : " + method.getName());
        }
        finally
        {
            // reset accessible value
            method.setAccessible(accessible);
        }
    }

    /**
     * Return a List of all methods of the qualifier,
     * which are not annotated with @Nonbinding.
     *
     * @param qualifierAnnotationType
     * @return
     */
    private static List<Method> getBindingQualifierMethods(Class<? extends Annotation> qualifierAnnotationType)
    {
        Method[] qualifierMethods = qualifierAnnotationType.getDeclaredMethods();
        if (qualifierMethods.length > 0)
        {
            List<Method> bindingMethods = new ArrayList<Method>();

            for (Method qualifierMethod : qualifierMethods)
            {
                Annotation[] qualifierMethodAnnotations = qualifierMethod.getDeclaredAnnotations();

                if (qualifierMethodAnnotations.length > 0)
                {
                    // look for @Nonbinding
                    boolean nonbinding = false;

                    for (Annotation qualifierMethodAnnotation : qualifierMethodAnnotations)
                    {
                        if (Nonbinding.class.equals(qualifierMethodAnnotation.annotationType()))
                        {
                            nonbinding = true;
                            break;
                        }
                    }

                    if (!nonbinding)
                    {
                        // no @Nonbinding found - add to list
                        bindingMethods.add(qualifierMethod);
                    }
                }
                else
                {
                    // no method-annotations - add to list
                    bindingMethods.add(qualifierMethod);
                }
            }

            return bindingMethods;
        }

        // annotation has no methods
        return Collections.emptyList();
    }

    public static <T> T lookupFromEnvironment(String systemPropertyName, String jndiName , Class<T> targetType)
    {
        String configuredValue = System.getProperty(systemPropertyName);
        if (configuredValue != null)
        {
            if(String.class.isAssignableFrom(targetType))
            {
                return (T)configuredValue;
            }
            return tryToInstantiateClassForName(configuredValue, targetType);
        }

        try
        {
            configuredValue = JndiUtils.lookup(jndiName, String.class);
        }
        catch (RuntimeException jndiException)
        {
            // noop - lookup did not work
        }

        if (configuredValue != null)
        {
            if(String.class.isAssignableFrom(targetType))
            {
                return (T)configuredValue;
            }
            return tryToInstantiateClassForName(configuredValue, targetType);
        }

        return null;
    }

    public static boolean isCdiInitialized()
    {
        return BeanManagerProvider.getInstance() != null;
    }
}
TOP

Related Classes of org.apache.myfaces.extensions.cdi.core.impl.util.CodiUtils

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.