Package org.apache.webbeans.util

Source Code of org.apache.webbeans.util.ClassUtil

/*
* 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.util;

import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.security.PrivilegedActionException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.enterprise.event.Event;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.inject.Provider;

import org.apache.webbeans.config.BeanTypeSetResolver;
import org.apache.webbeans.config.WebBeansContext;
import org.apache.webbeans.exception.WebBeansException;
import org.apache.webbeans.logger.WebBeansLoggerFacade;

/**
* Utility classes with respect to the class operations.
*
* @author <a href="mailto:gurkanerdogdu@yahoo.com">Gurkan Erdogdu</a>
* @since 1.0
*/
@SuppressWarnings("unchecked")
public final class ClassUtil
{
    public static final Map<Class<?>, Class<?>> PRIMITIVE_TO_WRAPPERS_MAP = new HashMap<Class<?>, Class<?>>();

    private static final Logger logger = WebBeansLoggerFacade.getLogger(ClassUtil.class);

    static
    {
        PRIMITIVE_TO_WRAPPERS_MAP.put(Integer.TYPE,Integer.class);
        PRIMITIVE_TO_WRAPPERS_MAP.put(Float.TYPE,Float.class);
        PRIMITIVE_TO_WRAPPERS_MAP.put(Double.TYPE,Double.class);
        PRIMITIVE_TO_WRAPPERS_MAP.put(Character.TYPE,Character.class);
        PRIMITIVE_TO_WRAPPERS_MAP.put(Long.TYPE,Long.class);
        PRIMITIVE_TO_WRAPPERS_MAP.put(Byte.TYPE,Byte.class);
        PRIMITIVE_TO_WRAPPERS_MAP.put(Short.TYPE,Short.class);
        PRIMITIVE_TO_WRAPPERS_MAP.put(Boolean.TYPE,Boolean.class);
        PRIMITIVE_TO_WRAPPERS_MAP.put(Void.TYPE,Void.class);
    }

    /*
     * Private constructor
     */
    private ClassUtil()
    {
        throw new UnsupportedOperationException();
    }

    public static Object newInstance(WebBeansContext webBeansContext, Class<?> clazz)
    {
        try
        {
            if(System.getSecurityManager() != null)
            {
                return webBeansContext.getSecurityService().doPrivilegedObjectCreate(clazz);
            }           
           
            return clazz.newInstance();
           
        }
        catch(Exception e)
        {
            Throwable cause = e;
            if(e instanceof PrivilegedActionException)
            {
                cause = e.getCause();
            }
           
            String error = "Error occurred while creating an instance of class : " + clazz.getName();
            logger.log(Level.SEVERE, error, cause);
            throw new WebBeansException(error,cause);
       
        }
    }

    public static Class<?> getClassFromName(String name)
    {
        Class<?> clazz = null;
        ClassLoader loader = null;
        try
        {
            loader = WebBeansUtil.getCurrentClassLoader();
            clazz = Class.forName(name, true , loader);
            //X clazz = loader.loadClass(name);
            return clazz;

        }
        catch (ClassNotFoundException e)
        {
            try
            {
                loader = ClassUtil.class.getClassLoader();
                clazz = Class.forName(name, true , loader);

                return clazz;

            }
            catch (ClassNotFoundException e1)
            {
                try
                {
                    loader = ClassLoader.getSystemClassLoader();
                    clazz = Class.forName(name, true , loader);

                    return clazz;

                }
                catch (ClassNotFoundException e2)
                {
                    return null;
                }

            }
        }

    }

    /**
     * Check final modifier.
     *
     * @param modifier modifier
     * @return true or false
     */
    public static boolean isFinal(Integer modifier)
    {
        Asserts.nullCheckForModifier(modifier);

        return Modifier.isFinal(modifier);
    }

    /**
     * Check abstract modifier.
     *
     * @param modifier modifier
     * @return true or false
     */
    public static boolean isAbstract(Integer modifier)
    {
        Asserts.nullCheckForModifier(modifier);

        return Modifier.isAbstract(modifier);
    }

    /**
     * Check interface modifier.
     *
     * @param modifier modifier
     * @return true or false
     */
    public static boolean isInterface(Integer modifier)
    {
        Asserts.nullCheckForModifier(modifier);

        return Modifier.isInterface(modifier);
    }

    /**
     * Check for class that has a final method or not.
     *
     * @param clazz check methods of it
     * @return true or false
     */
    public static boolean hasFinalMethod(Class<?> clazz)
    {
        Asserts.nullCheckForClass(clazz);

        Method[] methods = SecurityUtil.doPrivilegedGetDeclaredMethods(clazz);
        for (Method m : methods)
        {
            if (isFinal(m.getModifiers()))
            {
                return true;
            }
        }

        return false;
    }

    /**
     * Check the class is inner or not
     *
     * @param clazz to check
     * @return true or false
     */
    public static boolean isInnerClazz(Class<?> clazz)
    {
        Asserts.nullCheckForClass(clazz);

        return clazz.isMemberClass();
    }

    public static Class<?>  getPrimitiveWrapper(Class<?> clazz)
    {
        Asserts.nullCheckForClass(clazz);
       
        return PRIMITIVE_TO_WRAPPERS_MAP.get(clazz);

    }
   

    /**
     * Gets the class of the given type arguments.
     * <p>
     * If the given type {@link Type} parameters is an instance of the
     * {@link ParameterizedType}, it returns the raw type otherwise it return
     * the casted {@link Class} of the type argument.
     * </p>
     *
     * @param type class or parametrized type
     * @return
     */
    public static Class<?> getClass(Type type)
    {
        return getClazz(type);
    }

    /**
     * Gets the declared methods of the given class.
     *
     * @param clazz class instance
     * @return the declared methods
     */
    public static Method[] getDeclaredMethods(Class<?> clazz)
    {
        Asserts.nullCheckForClass(clazz);
        return SecurityUtil.doPrivilegedGetDeclaredMethods(clazz);
    }

    /**
     * Check that method has any formal arguments.
     *
     * @param method method instance
     * @return true or false
     */
    public static boolean isMethodHasParameter(Method method)
    {
        Asserts.nullCheckForMethod(method);

        return method.getParameterTypes().length > 0;
    }

    /**
     * Gets the return type of the method.
     *
     * @param method method instance
     * @return return type
     */
    public static Class<?> getReturnType(Method method)
    {
        Asserts.nullCheckForMethod(method);
        return method.getReturnType();
    }

    /**
     * Check method throws checked exception or not.
     *
     * @param method method instance
     */
    public static boolean isMethodHasCheckedException(Method method)
    {
        Asserts.nullCheckForMethod(method);

        Class<?>[] et = method.getExceptionTypes();

        if (et.length > 0)
        {
            for (Class<?> type : et)
            {
                if (!Error.class.isAssignableFrom(type) && !RuntimeException.class.isAssignableFrom(type))
                {
                    return true;
                }
            }

        }

        return false;
    }

    /**
     * Call method on the instance with given arguments.
     *
     * @param method method instance
     * @param instance object instance
     * @param args arguments
     * @return the method result
     */
    public static Object callInstanceMethod(Method method, Object instance, Object[] args)
    {
        Asserts.nullCheckForMethod(method);
        Asserts.assertNotNull(instance, "instance parameter can not be null");

        try
        {
            if (args == null)
            {
                args = new Object[] {};
            }
            return method.invoke(instance, args);

        }
        catch (Exception e)
        {
            throw new WebBeansException("Exception occurs in the method call with method : " + method.getName() + " in class : " + instance.getClass().getName(), e);
        }

    }

    public static List<Class<?>> getSuperClasses(Class<?> clazz, List<Class<?>> list)
    {
        Asserts.nullCheckForClass(clazz);

        Class<?> sc = clazz.getSuperclass();
        if (sc != null)
        {
            list.add(sc);
            getSuperClasses(sc, list);
        }

        return list;

    }

    public static Class<?>[] getMethodParameterTypes(Method method)
    {
        Asserts.nullCheckForMethod(method);
        return method.getParameterTypes();
    }

    private static Set<String> getObjectMethodNames()
    {
        if (objectMethodNames == null)
        {
            // not much synchronisation needed...
            Set<String> list = new HashSet<String>();
            Class<?> clazz = Object.class;

            Method[] methods = SecurityUtil.doPrivilegedGetDeclaredMethods(clazz);
            for (Method method : methods)
            {
                list.add(method.getName());
            }
            objectMethodNames = list;
        }

        return objectMethodNames;
    }
    private static volatile Set<String> objectMethodNames= null;
   


    public static boolean isObjectMethod(String methodName)
    {
        return getObjectMethodNames().contains(methodName);
    }

    public static boolean isMoreThanOneMethodWithName(String methodName, Class<?> clazz)
    {
        Asserts.assertNotNull(methodName, "methodName parameter can not be null");
        Asserts.nullCheckForClass(clazz);

        Method[] methods = SecurityUtil.doPrivilegedGetDeclaredMethods(clazz);
        int methodCount = 0;
        for (Method m : methods)
        {
            if (m.getName().equals(methodName))
            {
                methodCount++;
            }
        }

        return methodCount > 1;

    }

    /**
     * Gets java package if exist.
     *
     * @param packageName package name
     * @return the package with given name
     */
    public Package getPackage(String packageName)
    {
        Asserts.assertNotNull(packageName, "packageName parameter can not be null");

        return Package.getPackage(packageName);
    }

    /**
     * Returns true if type is an instance of <code>ParameterizedType</code>
     * else otherwise.
     *
     * @param type type of the artifact
     * @return true if type is an instance of <code>ParameterizedType</code>
     */
    public static boolean isParametrizedType(Type type)
    {
        Asserts.assertNotNull(type, "type parameter can not be null");
        if (type instanceof ParameterizedType)
        {
            return true;
        }

        return false;
    }
   
    /**
     * Returns true if type is an instance of <code>WildcardType</code>
     * else otherwise.
     *
     * @param type type of the artifact
     * @return true if type is an instance of <code>WildcardType</code>
     */   
    public static boolean isWildCardType(Type type)
    {
        Asserts.assertNotNull(type, "type parameter can not be null");
       
        return type instanceof WildcardType;
    }
   
    public static boolean isUnboundedTypeVariable(Type type)
    {
        Asserts.assertNotNull(type, "type parameter can not be null");
       
        if (type instanceof TypeVariable)
        {
            TypeVariable wc = (TypeVariable)type;
            Type[] upper = wc.getBounds();           
           
           
            if(upper.length > 1)
            {
                return false;
            }           
            else
            {
                Type arg = upper[0];
                if(!(arg instanceof Class))
                {
                    return false;
                }
                else
                {
                    Class<?> clazz = (Class<?>)arg;
                    if(!clazz.equals(Object.class))
                    {
                        return false;
                    }                   
                }
            }           
        }
        else
        {
            return false;
        }

        return true;
    }
   
   
    /**
     * Returns true if type is an instance of <code>TypeVariable</code>
     * else otherwise.
     *
     * @param type type of the artifact
     * @return true if type is an instance of <code>TypeVariable</code>
     */   
    public static boolean isTypeVariable(Type type)
    {
        Asserts.assertNotNull(type, "type parameter can not be null");

        return type instanceof TypeVariable;
    }
   

    /**
     * Returna true if the class is not abstract and interface.
     *    
     * @param clazz class type
     * @return true if the class is not abstract and interface
     */
    public static boolean isConcrete(Class<?> clazz)
    {
        Asserts.nullCheckForClass(clazz);

        Integer modifier = clazz.getModifiers();

        if (!isAbstract(modifier) && !isInterface(modifier))
        {
            return true;
        }

        return false;
    }

    /**
     * See specification 5.2.3.
     * @param beanType bean type
     * @param requiredType required type
     * @return true if assignable
     */
    public static boolean isAssignable(Type beanType, Type requiredType)
    {
        Asserts.assertNotNull(beanType, "beanType parameter can not be null");
        Asserts.assertNotNull(requiredType, "requiredType parameter can not be null");
       
        //Bean and required types are ParametrizedType
        if (beanType instanceof ParameterizedType && requiredType instanceof ParameterizedType)
        {
            return isAssignableForParametrized((ParameterizedType) beanType, (ParameterizedType) requiredType);
        }
        //Both type is class type
        else if (beanType instanceof Class && requiredType instanceof Class)
        {
            Class<?> clzBeanType = (Class<?>)beanType;
            Class<?> clzReqType = (Class<?>)requiredType;
           
            if(clzBeanType.isPrimitive())
            {
                clzBeanType = getPrimitiveWrapper(clzBeanType);
            }
           
            if(clzReqType.isPrimitive())
            {
                clzReqType = getPrimitiveWrapper(clzReqType);
            }
           
            return clzReqType.equals(clzBeanType);
        }
        //Bean type is Parametrized and required type is class type
        else if(beanType instanceof ParameterizedType && requiredType instanceof Class)
        {
            boolean ok = true;
            ParameterizedType ptBean = (ParameterizedType)beanType;
            Class<?> clazzBeanType = (Class<?>)ptBean.getRawType();
            Class<?> clazzReqType = (Class<?>)requiredType;
            if(isClassAssignable(clazzReqType, clazzBeanType ))
            {
                Type[]  beanTypeArgs = ptBean.getActualTypeArguments();              
                for(Type actual : beanTypeArgs)
                {
                    if(!ClassUtil.isUnboundedTypeVariable(actual))
                    {
                        if(actual instanceof Class)
                        {
                            Class<?> clazz = (Class<?>)actual;
                            if(!clazz.equals(Object.class))
                            {
                                ok = false;
                                break;
                            }
                        }
                        else
                        {
                            ok = false;
                            break;
                        }
                    }
                }               
            }
            else
            {
                ok = false;
            }
           
           
            return ok;
        }
        //Bean type is class and required type is parametrized
        else if(beanType instanceof Class && requiredType instanceof ParameterizedType)
        {
            Class<?> clazzBeanType = (Class<?>)beanType;
            ParameterizedType ptReq = (ParameterizedType)requiredType;
            Class<?> clazzReqType = (Class<?>)ptReq.getRawType();
           
            if(Provider.class.isAssignableFrom(clazzReqType) ||
                    Event.class.isAssignableFrom(clazzReqType))
            {
                if(isClassAssignable(clazzReqType, clazzBeanType))
                {
                    return true;
                }   
            }
                       
            return false;
        }
        else
        {
            return false;
        }
    }

    /**
     * Checks that event is applicable
     * for the given observer type.
     * @param eventType event type
     * @param observerType observer type
     * @return true if event is applicable
     */
    public static boolean checkEventTypeAssignability(Type eventType, Type observerType)
    {
        //Observer type is a TypeVariable
        if(isTypeVariable(observerType))
        {
            Class<?> eventClass = getClass(eventType);
                       
            TypeVariable<?> tvBeanTypeArg = (TypeVariable<?>)observerType;
            Type tvBound = tvBeanTypeArg.getBounds()[0];
           
            if(tvBound instanceof Class)
            {
                Class<?> clazzTvBound = (Class<?>)tvBound;               
                if(clazzTvBound.isAssignableFrom(eventClass))
                {
                    return true;
                }                   
            }
        }
        //Both of them are ParametrizedType
        else if(observerType instanceof ParameterizedType && eventType instanceof ParameterizedType)
        {
            return isAssignableForParametrized((ParameterizedType)eventType, (ParameterizedType)observerType);
        }
        //Observer is class and Event type is Parametrized
        else if(observerType instanceof Class && eventType instanceof ParameterizedType)
        {
            Class<?> clazzBeanType = (Class<?>)observerType;
            ParameterizedType ptEvent = (ParameterizedType)eventType;
            Class<?> eventClazz = (Class<?>)ptEvent.getRawType();
           
            if(isClassAssignable(clazzBeanType, eventClazz))
            {
                return true;
            }
           
            return false;           
        }
        //Both of them is class type
        else if(observerType instanceof Class && eventType instanceof Class)
        {
            return isClassAssignable((Class<?>)observerType, (Class<?>) eventType);
        }
       
        return false;
    }
   
   
    /**
     * Returns true if rhs is assignable type
     * to the lhs, false otherwise.
     *
     * @param lhs left hand side class
     * @param rhs right hand side class
     * @return true if rhs is assignable to lhs
     */
    public static boolean isClassAssignable(Class<?> lhs, Class<?> rhs)
    {
        Asserts.assertNotNull(lhs, "lhs parameter can not be null");
        Asserts.assertNotNull(rhs, "rhs parameter can not be null");

        if(lhs.isPrimitive())
        {
            lhs = getPrimitiveWrapper(lhs);
        }
       
        if(rhs.isPrimitive())
        {
            rhs = getPrimitiveWrapper(rhs);
        }
       
        if (lhs.isAssignableFrom(rhs))
        {
            return true;
        }

        return false;
    }

    /**
     * Returns true if given bean's api type is injectable to
     * injection point required type.
     *
     * @param beanType bean parametrized api type
     * @param requiredType injection point parametrized api type
     * @return if injection is possible false otherwise
     */
    public static boolean isAssignableForParametrized(ParameterizedType beanType, ParameterizedType requiredType)
    {
        Class<?> beanRawType = (Class<?>) beanType.getRawType();
        Class<?> requiredRawType = (Class<?>) requiredType.getRawType();

        if (ClassUtil.isClassAssignable(requiredRawType,beanRawType))
        {
            //Bean api type actual type arguments
            Type[] beanTypeArgs = beanType.getActualTypeArguments();
           
            //Injection point type actual arguments
            Type[] requiredTypeArgs = requiredType.getActualTypeArguments();
           
            if(beanTypeArgs.length != requiredTypeArgs.length)
            {               
                return false;
            }
            else
            {
                return isAssignableForParametrizedCheckArguments(beanTypeArgs, requiredTypeArgs);
            }
        }

        return false;
    }
   
    /**
     * Check parametrized type actual type arguments.
     * @param beanTypeArgs bean type actual type arguments
     * @param requiredTypeArgs required type actual type arguments.
     * @return true if assignment applicable
     */
    private static boolean isAssignableForParametrizedCheckArguments(Type[] beanTypeArgs, Type[] requiredTypeArgs)
    {
        Type requiredTypeArg = null;
        Type beanTypeArg = null;
        for(int i = 0; i< requiredTypeArgs.length;i++)
        {
            requiredTypeArg = requiredTypeArgs[i];
            beanTypeArg = beanTypeArgs[i];
           
            //Required type is parametrized and bean type is parametrized
            if(ClassUtil.isParametrizedType(requiredTypeArg) && ClassUtil.isParametrizedType(beanTypeArg))
            {
                return checkBeanAndRequiredTypeIsParametrized(beanTypeArg, requiredTypeArg);
            }
            //Required type is wildcard
            else if(ClassUtil.isWildCardType(requiredTypeArg))
            {
                return checkRequiredTypeIsWildCard(beanTypeArg, requiredTypeArg);
            }
            //Required type is actual type and bean type is type variable
            else if(requiredTypeArg instanceof Class && ClassUtil.isTypeVariable(beanTypeArg))
            {
                return checkRequiredTypeIsClassAndBeanTypeIsVariable(beanTypeArg, requiredTypeArg);
            }
            //Required type is Type variable and bean type is type variable
            else if(ClassUtil.isTypeVariable(requiredTypeArg) && ClassUtil.isTypeVariable(beanTypeArg))
            {
                return checkBeanTypeAndRequiredIsTypeVariable(beanTypeArg, requiredTypeArg);
            }     
           
            //Both type is actual type
            else if((beanTypeArg instanceof Class) && (requiredTypeArg instanceof Class))
            {
                if(isClassAssignable((Class<?>)requiredTypeArg,(Class<?>)beanTypeArg))
                {
                    return true;
                }
            }
            //Bean type is actual type and required type is type variable
            else if((beanTypeArg instanceof Class) && (ClassUtil.isTypeVariable(requiredTypeArg)))
            {
                return checkRequiredTypeIsTypeVariableAndBeanTypeIsClass(beanTypeArg, requiredTypeArg);
            }
        }
       
        return false;
    }

    /**
     * Check parametrized bean type and parametrized
     * required types.
     * @param beanTypeArg parametrized bean type
     * @param requiredTypeArg parametrized required type
     * @return true if types are assignables
     * @since 1.1.1
     */
    public static boolean checkBeanAndRequiredTypeIsParametrized(Type beanTypeArg, Type requiredTypeArg)
    {
        ParameterizedType ptRequiredTypeArg = (ParameterizedType)requiredTypeArg;
        ParameterizedType ptBeanTypeArg = (ParameterizedType)beanTypeArg;
       
        //Equal raw types
        if(ptRequiredTypeArg.getRawType().equals(ptBeanTypeArg.getRawType()))
        {
            //Check arguments
            Type[] actualArgsRequiredType = ptRequiredTypeArg.getActualTypeArguments();
            Type[] actualArgsBeanType = ptRequiredTypeArg.getActualTypeArguments();
           
            if(actualArgsRequiredType.length > 0 && actualArgsBeanType.length == actualArgsRequiredType.length)
            {
                return isAssignableForParametrizedCheckArguments(actualArgsBeanType, actualArgsRequiredType);
            }
            else
            {
                return true;
            }
        }
       
        return false;
    }

    /**
     * Check bean type and required type.
     * <p>
     * Required type is a wildcard type.
     * </p>
     * @param beanTypeArg bean type
     * @param requiredTypeArg required type
     * @return true if condition satisfies
     * @since 1.1.1
     */
    public static boolean checkRequiredTypeIsWildCard(Type beanTypeArg, Type requiredTypeArg)
    {
        WildcardType wctRequiredTypeArg = (WildcardType)requiredTypeArg;
        Type upperBoundRequiredTypeArg =  wctRequiredTypeArg.getUpperBounds()[0];
        Type[] lowerBoundRequiredTypeArgs =  wctRequiredTypeArg.getLowerBounds();
       
        if(beanTypeArg instanceof Class)
        {
            Class<?> clazzBeanTypeArg = (Class<?>)beanTypeArg;
            if(upperBoundRequiredTypeArg instanceof Class)
            {
                //Check upper bounds
                Class<?> clazzUpperBoundTypeArg = (Class<?>)upperBoundRequiredTypeArg;
                if(clazzUpperBoundTypeArg != Object.class)
                {
                    if(!clazzUpperBoundTypeArg.isAssignableFrom(clazzBeanTypeArg))
                    {                                      
                        return false;
                    }
                }
               
                //Check lower bounds
                if(lowerBoundRequiredTypeArgs.length > 0 &&  lowerBoundRequiredTypeArgs[0] instanceof Class)
                {
                    Class<?> clazzLowerBoundTypeArg = (Class<?>)lowerBoundRequiredTypeArgs[0];
                   
                    if(clazzLowerBoundTypeArg != Object.class)
                    {
                        if(!clazzBeanTypeArg.isAssignableFrom(clazzLowerBoundTypeArg))
                        {
                            return false;
                        }                               
                    }
                }
            }                   
        }
        else if(ClassUtil.isTypeVariable(beanTypeArg))
        {
            TypeVariable<?> tvBeanTypeArg = (TypeVariable<?>)beanTypeArg;
            Type tvBound = tvBeanTypeArg.getBounds()[0];
           
            if(tvBound instanceof Class)
            {
                Class<?> clazzTvBound = (Class<?>)tvBound;
               
                if(upperBoundRequiredTypeArg instanceof Class)
                {
                    Class<?> clazzUpperBoundTypeArg = (Class<?>)upperBoundRequiredTypeArg;                   
                    if(clazzUpperBoundTypeArg != Object.class && clazzTvBound != Object.class)
                    {
                        if(!clazzUpperBoundTypeArg.isAssignableFrom(clazzTvBound))
                        {  
                            return false;
                        }                      
                    }
                   
                    //Check lower bounds
                    if(lowerBoundRequiredTypeArgs.length > 0 &&  lowerBoundRequiredTypeArgs[0] instanceof Class)
                    {
                        Class<?> clazzLowerBoundTypeArg = (Class<?>)lowerBoundRequiredTypeArgs[0];
                       
                        if(clazzLowerBoundTypeArg != Object.class)
                        {
                            if(!clazzTvBound.isAssignableFrom(clazzLowerBoundTypeArg))
                            {
                                return false;
                            }                                   
                        }
                    }                   
                }                                   
            }
        }
        
        return true;
    }
   
    /**
     * Checking bean type and required type.
     * <p>
     * Required type is class and bean type is
     * a type variable.
     * </p>
     * @param beanTypeArg bean type
     * @param requiredTypeArg required type
     * @return true if condition satisfy
     */
    public static boolean checkRequiredTypeIsClassAndBeanTypeIsVariable(Type beanTypeArg, Type requiredTypeArg)
    {
        Class<?> clazzRequiredType = (Class<?>)requiredTypeArg;
       
        TypeVariable<?> tvBeanTypeArg = (TypeVariable<?>)beanTypeArg;
        Type tvBound = tvBeanTypeArg.getBounds()[0];
       
        if(tvBound instanceof Class)
        {
            Class<?> clazzTvBound = (Class<?>)tvBound;
           
            if(clazzTvBound != Object.class)
            {
                if(!clazzTvBound.isAssignableFrom(clazzRequiredType))
                {
                    return false;
                }                                   
            }           
        }
       
        return true;
    }
   
    public static boolean checkRequiredTypeIsTypeVariableAndBeanTypeIsClass(Type beanTypeArg, Type requiredTypeArg)
    {
        Class<?> clazzBeanType = (Class<?>)beanTypeArg;
       
        TypeVariable<?> tvRequiredTypeArg = (TypeVariable<?>)requiredTypeArg;
        Type tvBound = tvRequiredTypeArg.getBounds()[0];
       
        if(tvBound instanceof Class)
        {
            Class<?> clazzTvBound = (Class<?>)tvBound;
           
            if(clazzTvBound.isAssignableFrom(clazzBeanType))
            {
                return true;
            }                   
        }
       
        return false;
    }
   

    public static boolean checkBeanTypeAndRequiredIsTypeVariable(Type beanTypeArg, Type requiredTypeArg)
    {
        TypeVariable<?> tvBeanTypeArg = (TypeVariable<?>)beanTypeArg;
        Type tvBeanBound = tvBeanTypeArg.getBounds()[0];
       
        TypeVariable<?> tvRequiredTypeArg = (TypeVariable<?>)requiredTypeArg;
        Type tvRequiredBound = tvRequiredTypeArg.getBounds()[0];
       
        if(tvBeanBound instanceof Class && tvRequiredBound instanceof Class)
        {
            Class<?> clazzTvBeanBound = (Class<?>)tvBeanBound;
            Class<?> clazzTvRequiredBound = (Class<?>)tvRequiredBound;
           
            if(clazzTvBeanBound.isAssignableFrom(clazzTvRequiredBound))
            {
                return true;
            }                   
        }
       
        return false;
    }

    /**
     * @param clazz webbeans implementation class
     * @param methodName name of the method that is searched
     * @param parameterTypes parameter types of the method(it can be subtype of
     *            the actual type arguments of the method)
     * @return the list of method that satisfies the condition
     */
    public static List<Method> getClassMethodsWithTypes(Class<?> clazz, String methodName, List<Class<?>> parameterTypes)
    {
        Asserts.nullCheckForClass(clazz);
        Asserts.assertNotNull(methodName, "methodName parameter can not be null");
        Asserts.assertNotNull(parameterTypes, "parameterTypes parameter can not be null");

        List<Method> methodList = new ArrayList<Method>();

        Method[] methods = SecurityUtil.doPrivilegedGetDeclaredMethods(clazz);

        int j = 0;
        for (Method method : methods)
        {
            if (method.getName().equals(methodName))
            {
                Class<?>[] defineTypes = method.getParameterTypes();

                if (defineTypes.length != parameterTypes.size())
                {
                    continue;
                }

                boolean ok = true;

                if (parameterTypes.size() > 0)
                {
                    ok = false;
                }

                if (!ok)
                {
                    for (Class<?> defineType : defineTypes)
                    {
                        if (defineType.isAssignableFrom(parameterTypes.get(j)))
                        {
                            ok = true;
                        }
                        else
                        {
                            ok = false;
                        }

                        j++;
                    }
                }

                if (ok)
                {
                    methodList.add(method);
                }
            }

        }

        return methodList;
    }

    public static Method getClassMethodWithTypes(Class<?> clazz, String methodName, List<Class<?>> parameterTypes)
    {
        Asserts.nullCheckForClass(clazz);
        Asserts.assertNotNull(methodName, "methodName parameter can not be null");
        Asserts.assertNotNull(parameterTypes, "parameterTypes parameter can not be null");

        Method[] methods = SecurityUtil.doPrivilegedGetDeclaredMethods(clazz);

        int j = 0;
        for (Method method : methods)
        {
            if (method.getName().equals(methodName))
            {
                if (parameterTypes != null && parameterTypes.size() > 0)
                {
                    Class<?>[] defineTypes = method.getParameterTypes();

                    if (defineTypes.length != parameterTypes.size())
                    {
                        continue;
                    }

                    boolean ok = false;

                    for (Class<?> defineType : defineTypes)
                    {
                        if (defineType.equals(parameterTypes.get(j)))
                        {
                            ok = true;
                        }
                        else
                        {
                            ok = false;
                        }
                    }

                    if (ok)
                    {
                        return method;
                    }
                }
                else
                {
                    return method;
                }
            }
        }

        return null;
    }

    public static boolean isArray(Class<?> clazz)
    {
        Asserts.nullCheckForClass(clazz);

        return clazz.isArray();
    }

    /**
     * Learn whether the specified class is defined with type parameters.
     * @param clazz to check
     * @return true if there are type parameters
     * @since 1.1.1
     */
    public static boolean isDefinitionContainsTypeVariables(Class<?> clazz)
    {
        Asserts.nullCheckForClass(clazz);
       
        return (clazz.getTypeParameters().length > 0) ? true : false;
    }

    /**
     * Returns declared type arguments if {@code type} is a
     * {@link ParameterizedType} instance, else an empty array.
     * Get the actual type arguments of a type.
     * @param type
     * @return array of type arguments available
     * @since 1.1.1
     */
    public static Type[] getActualTypeArguments(Type type)
    {
        Asserts.assertNotNull(type, "type parameter can not be null");

        if (type instanceof ParameterizedType)
        {
            return ((ParameterizedType) type).getActualTypeArguments();

        }
        else
        {
            return new Type[0];
        }
    }


    public static Set<Type> setTypeHierarchy(Set<Type> set, Type clazz)
    {
        BeanTypeSetResolver resolver = new BeanTypeSetResolver(clazz);
        resolver.startConfiguration();
        set.addAll(resolver.getHierarchy());
       
        return set;
    }

    /**
     * Return raw class type for given type.
     * @param type base type instance
     * @return class type for given type
     */
    public static Class<?> getClazz(Type type)
    {
        Class<?> raw = null;
       
        if(type instanceof ParameterizedType)
        {
            ParameterizedType pt = (ParameterizedType)type;
            raw = (Class<?>)pt.getRawType();               
        }
        else if(type instanceof Class)
        {
            raw = (Class<?>)type;
        }
        else if(type instanceof GenericArrayType)
        {
            GenericArrayType arrayType = (GenericArrayType)type;
            raw = getClazz(arrayType.getGenericComponentType());
        }
       
        return raw;
    }

    public static Set<Type> setInterfaceTypeHierarchy(Set<Type> set, Class<?> clazz)
    {
        Asserts.nullCheckForClass(clazz);

        do
        {
            Class<?>[] interfaces = clazz.getInterfaces();

            for (Class<?> cl : interfaces)
            {
                set.add(cl);

                setTypeHierarchy(set, cl);
            }
            clazz = clazz.getSuperclass();
        } while (clazz != null && clazz != Object.class);

        return set;
    }

    /**
     * Return true if it does not contain type variable for wildcard type
     * false otherwise.
     *
     * @param pType parameterized type
     * @return true if it does not contain type variable for wildcard type
     */
    public static boolean checkParametrizedType(ParameterizedType pType)
    {
        Asserts.assertNotNull(pType, "pType argument can not be null");
       
        Type[] types = pType.getActualTypeArguments();

        for (Type type : types)
        {
            if (type instanceof ParameterizedType)
            {
                return checkParametrizedType((ParameterizedType) type);
            }
            else if ((type instanceof TypeVariable) || (type instanceof WildcardType))
            {
                return false;
            }
        }

        return true;
    }

    public static Field[] getFieldsWithType(WebBeansContext webBeansContext, Class<?> clazz, Type type)
    {
        Asserts.nullCheckForClass(clazz);
        Asserts.assertNotNull(type, "type parameter can not be null");

        List<Field> fieldsWithType = new ArrayList<Field>();
        Field[] fields = webBeansContext.getSecurityService().doPrivilegedGetDeclaredFields(clazz);
        for (Field field : fields)
        {
            if(field.getType().equals(type))
            {
                fieldsWithType.add(field);
            }
        }

        return fieldsWithType.toArray(new Field[fieldsWithType.size()]);

    }

    /**
     * Returns injection point raw type.
     *
     * @param injectionPoint injection point definition
     * @return injection point raw type
     */
    public static Class<?> getRawTypeForInjectionPoint(InjectionPoint injectionPoint)
    {
        Class<?> rawType = null;
        Type type = injectionPoint.getType();
       
        if(type instanceof Class)
        {
            rawType = (Class<?>) type;
        }
        else if(type instanceof ParameterizedType)
        {
            ParameterizedType pt = (ParameterizedType)type;           
            rawType = (Class<?>)pt.getRawType();                                               
        }
       
        return rawType;
    }

    /**
     * Learn whether <code>superClassMethod</code> is overridden by <code>subClassMethod</code>.
     * @param subClassMethod potentially overriding
     * @param superClassMethod potentially overridden
     * @return true if overridden
     * @since 1.1.1
     */
    public static boolean isOverridden(Method subClassMethod, Method superClassMethod)
    {
        if (subClassMethod.getName().equals(superClassMethod.getName()) && Arrays.equals(subClassMethod.getParameterTypes(), superClassMethod.getParameterTypes()))
        {
            int modifiers = superClassMethod.getModifiers();
            if(Modifier.isPrivate(modifiers))
            {
                return false;
            }
           
            if(!Modifier.isProtected(modifiers) && !Modifier.isPublic(modifiers))                
            {
                Class<?> superClass = superClassMethod.getDeclaringClass();
                Class<?> subClass = subClassMethod.getDeclaringClass();
               
                //Same package
                if(!subClass.getPackage().getName().equals(superClass.getPackage().getName()))
                {
                    return false;
                }
            }
           
            return true;
        }
       
        return false;
    }
   
}
TOP

Related Classes of org.apache.webbeans.util.ClassUtil

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.