From commits-return-8284-archive-asf-public=cust-asf.ponee.io@openwebbeans.apache.org Sun Jun 23 09:10:33 2019 Return-Path: X-Original-To: archive-asf-public@cust-asf.ponee.io Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [207.244.88.153]) by mx-eu-01.ponee.io (Postfix) with SMTP id DB33F180679 for ; Sun, 23 Jun 2019 11:10:32 +0200 (CEST) Received: (qmail 14107 invoked by uid 500); 23 Jun 2019 09:10:32 -0000 Mailing-List: contact commits-help@openwebbeans.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@openwebbeans.apache.org Delivered-To: mailing list commits@openwebbeans.apache.org Received: (qmail 14095 invoked by uid 99); 23 Jun 2019 09:10:32 -0000 Received: from Unknown (HELO svn01-us-west.apache.org) (209.188.14.144) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 23 Jun 2019 09:10:32 +0000 Received: from svn01-us-west.apache.org (localhost [127.0.0.1]) by svn01-us-west.apache.org (ASF Mail Server at svn01-us-west.apache.org) with ESMTP id 847B63A0102 for ; Sun, 23 Jun 2019 09:10:31 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1861905 - in /openwebbeans/trunk/webbeans-impl/src: main/java/org/apache/webbeans/component/creation/ main/java/org/apache/webbeans/config/ main/java/org/apache/webbeans/container/ main/java/org/apache/webbeans/decorator/ main/java/org/apa... Date: Sun, 23 Jun 2019 09:10:31 -0000 To: commits@openwebbeans.apache.org From: rmannibucau@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20190623091031.847B63A0102@svn01-us-west.apache.org> Author: rmannibucau Date: Sun Jun 23 09:10:31 2019 New Revision: 1861905 URL: http://svn.apache.org/viewvc?rev=1861905&view=rev Log: OWB-1292 exit satisfiesDependency when generics loop Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/creation/AbstractBeanBuilder.java openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/creation/BaseProducerFactory.java openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/config/BeansDeployer.java openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/container/BeanManagerImpl.java openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/container/InjectionResolver.java openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/decorator/DecoratorsManager.java openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/event/NotificationManager.java openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/portable/EventProducer.java openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/util/GenericsUtil.java openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/util/WebBeansUtil.java openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/unittests/inject/parametrized/GenericClassTest.java openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/util/GenericsUtilTest.java Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/creation/AbstractBeanBuilder.java URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/creation/AbstractBeanBuilder.java?rev=1861905&r1=1861904&r2=1861905&view=diff ============================================================================== --- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/creation/AbstractBeanBuilder.java (original) +++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/creation/AbstractBeanBuilder.java Sun Jun 23 09:10:31 2019 @@ -27,6 +27,7 @@ import javax.enterprise.inject.spi.Annot import javax.enterprise.inject.spi.AnnotatedParameter; import javax.enterprise.inject.spi.AnnotatedType; import java.util.Collection; +import java.util.HashMap; import java.util.Set; import org.apache.webbeans.component.ProducerFieldBean; @@ -59,7 +60,7 @@ public abstract class AbstractBeanBuilde boolean found = false; for (ProducerMethodBean producer : producerBeans) { - if (GenericsUtil.satisfiesDependency(false, true, producer.getCreatorMethod().getGenericReturnType(), param.getBaseType())) + if (GenericsUtil.satisfiesDependency(false, true, producer.getCreatorMethod().getGenericReturnType(), param.getBaseType(), new HashMap<>())) { found = true; break; @@ -69,7 +70,7 @@ public abstract class AbstractBeanBuilde { for (ProducerFieldBean field : producerFields) { - if (GenericsUtil.satisfiesDependency(false, true, field.getCreatorField().getType(), param.getBaseType())) + if (GenericsUtil.satisfiesDependency(false, true, field.getCreatorField().getType(), param.getBaseType(), new HashMap<>())) { found = true; break; @@ -81,7 +82,7 @@ public abstract class AbstractBeanBuilde // see if @Disposes should just be ignored as well - no inheritance for (AnnotatedMethod producer : ignoredProducers) { - if (GenericsUtil.satisfiesDependency(false, true, producer.getJavaMember().getGenericReturnType(), param.getBaseType())) + if (GenericsUtil.satisfiesDependency(false, true, producer.getJavaMember().getGenericReturnType(), param.getBaseType(), new HashMap<>())) { found = true; break; Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/creation/BaseProducerFactory.java URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/creation/BaseProducerFactory.java?rev=1861905&r1=1861904&r2=1861905&view=diff ============================================================================== --- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/creation/BaseProducerFactory.java (original) +++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/creation/BaseProducerFactory.java Sun Jun 23 09:10:31 2019 @@ -43,6 +43,7 @@ import javax.inject.Named; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.Set; @@ -102,7 +103,7 @@ public abstract class BaseProducerFactor { if (annotatedParameter.isAnnotationPresent(Disposes.class)) { - if (!GenericsUtil.satisfiesDependency(false, true, producerBaseType, annotatedParameter.getBaseType())) + if (!GenericsUtil.satisfiesDependency(false, true, producerBaseType, annotatedParameter.getBaseType(), new HashMap<>())) { continue; } Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/config/BeansDeployer.java URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/config/BeansDeployer.java?rev=1861905&r1=1861904&r2=1861905&view=diff ============================================================================== --- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/config/BeansDeployer.java (original) +++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/config/BeansDeployer.java Sun Jun 23 09:10:31 2019 @@ -597,7 +597,7 @@ public class BeansDeployer ParameterizedType pt2 = ParameterizedType.class.cast(t); if (pt1.getRawType() == pt2.getRawType() && - !GenericsUtil.isAssignableFrom(true, false, pt1, pt2)) + !GenericsUtil.isAssignableFrom(true, false, pt1, pt2, new HashMap<>())) { throw new WebBeansConfigurationException("Generic error matching " + api + " and " + t); } Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/container/BeanManagerImpl.java URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/container/BeanManagerImpl.java?rev=1861905&r1=1861904&r2=1861905&view=diff ============================================================================== --- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/container/BeanManagerImpl.java (original) +++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/container/BeanManagerImpl.java Sun Jun 23 09:10:31 2019 @@ -755,8 +755,8 @@ public class BeanManagerImpl implements boolean isProducer = AbstractProducerBean.class.isInstance(bean); if(!isProducer && // we have different rules for producers !isBeanTypeAssignableToGivenType(bean.getTypes(), beanType, bean instanceof NewBean, isProducer) && - !GenericsUtil.satisfiesDependency(false, isProducer, beanType, bean.getBeanClass()) && - !GenericsUtil.satisfiesDependencyRaw(false, isProducer, beanType, bean.getBeanClass())) + !GenericsUtil.satisfiesDependency(false, isProducer, beanType, bean.getBeanClass(), new HashMap<>()) && + !GenericsUtil.satisfiesDependencyRaw(false, isProducer, beanType, bean.getBeanClass(), new HashMap<>())) { throw new IllegalArgumentException("Given bean type : " + beanType + " is not applicable for the bean instance : " + bean); } @@ -934,7 +934,7 @@ public class BeanManagerImpl implements { for (Type beanApiType : beanTypes) { - if (GenericsUtil.satisfiesDependency(false, producer, givenType, beanApiType)) + if (GenericsUtil.satisfiesDependency(false, producer, givenType, beanApiType, new HashMap<>())) { return true; } Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/container/InjectionResolver.java URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/container/InjectionResolver.java?rev=1861905&r1=1861904&r2=1861905&view=diff ============================================================================== --- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/container/InjectionResolver.java (original) +++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/container/InjectionResolver.java Sun Jun 23 09:10:31 2019 @@ -54,6 +54,7 @@ import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.lang.reflect.WildcardType; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -514,7 +515,7 @@ public class InjectionResolver if (GenericsUtil.satisfiesDependency( isDelegate, AbstractProducerBean.class.isInstance(component), - injectionPointType, componentApiType)) + injectionPointType, componentApiType, new HashMap<>())) { resolvedComponents.add(component); break; @@ -599,7 +600,7 @@ public class InjectionResolver boolean isProducer = AbstractProducerBean.class.isInstance(bean); for (Type type : bean.getTypes()) { - if (GenericsUtil.satisfiesDependency(isDelegate, isProducer, injectionPointType, type)) + if (GenericsUtil.satisfiesDependency(isDelegate, isProducer, injectionPointType, type, new HashMap<>())) { resolved.add(bean); } @@ -625,7 +626,7 @@ public class InjectionResolver for (Type componentApiType : component.getTypes()) { - if (GenericsUtil.satisfiesDependency(isDelegate, isProducer, injectionPointType, componentApiType)) + if (GenericsUtil.satisfiesDependency(isDelegate, isProducer, injectionPointType, componentApiType, new HashMap<>())) { resolvedComponents.add(component); break; Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/decorator/DecoratorsManager.java URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/decorator/DecoratorsManager.java?rev=1861905&r1=1861904&r2=1861905&view=diff ============================================================================== --- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/decorator/DecoratorsManager.java (original) +++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/decorator/DecoratorsManager.java Sun Jun 23 09:10:31 2019 @@ -21,6 +21,7 @@ package org.apache.webbeans.decorator; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -238,7 +239,7 @@ public class DecoratorsManager boolean ok = false; for (Type apiType : apiTypes) { - if (GenericsUtil.satisfiesDependency(true, false, decorator.getDelegateType(), apiType)) + if (GenericsUtil.satisfiesDependency(true, false, decorator.getDelegateType(), apiType, new HashMap<>())) { ok = true; break; Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/event/NotificationManager.java URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/event/NotificationManager.java?rev=1861905&r1=1861904&r2=1861905&view=diff ============================================================================== --- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/event/NotificationManager.java (original) +++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/event/NotificationManager.java Sun Jun 23 09:10:31 2019 @@ -29,6 +29,7 @@ import java.lang.reflect.TypeVariable; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; @@ -346,8 +347,8 @@ public final class NotificationManager for (Type eventType : eventTypes) { if ((ParameterizedType.class.isInstance(eventType) && Class.class.isInstance(observedType) - && GenericsUtil.isAssignableFrom(true, false, observedType, ParameterizedType.class.cast(eventType).getRawType())) - || GenericsUtil.isAssignableFrom(true, false, observedType, eventType)) + && GenericsUtil.isAssignableFrom(true, false, observedType, ParameterizedType.class.cast(eventType).getRawType(), new HashMap<>())) + || GenericsUtil.isAssignableFrom(true, false, observedType, eventType, new HashMap<>())) { Set> observerMethods = observerEntry.getValue(); @@ -498,7 +499,7 @@ public final class NotificationManager } else if (observerTypeActualArg instanceof ParameterizedType) { - return GenericsUtil.isAssignableFrom(false, true, observerTypeActualArg, beanClass); + return GenericsUtil.isAssignableFrom(false, true, observerTypeActualArg, beanClass, new HashMap<>()); } return false; @@ -533,7 +534,7 @@ public final class NotificationManager if(checkEventTypeParameterForExtensions(beanClass, actualArgs[0]) && (secondParam == null || actualArgs.length == 1 || checkEventTypeParameterForExtensions(secondParam, actualArgs[1]) - || GenericsUtil.isAssignableFrom(true, false, actualArgs[1], secondParam))) + || GenericsUtil.isAssignableFrom(true, false, actualArgs[1], secondParam, new HashMap<>()))) { addToMatching(type, matching); } Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/portable/EventProducer.java URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/portable/EventProducer.java?rev=1861905&r1=1861904&r2=1861905&view=diff ============================================================================== --- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/portable/EventProducer.java (original) +++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/portable/EventProducer.java Sun Jun 23 09:10:31 2019 @@ -22,6 +22,7 @@ import java.lang.annotation.Annotation; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -64,7 +65,8 @@ public class EventProducer extends Ab { ParameterizedType arg = ParameterizedType.class.cast(event); Type[] actualTypeArguments = arg.getActualTypeArguments(); - if (actualTypeArguments.length > 0 && GenericsUtil.isAssignableFrom(true, false, actualTypeArguments[0], type)) + if (actualTypeArguments.length > 0 && GenericsUtil.isAssignableFrom( + true, false, actualTypeArguments[0], type, new HashMap<>())) { list.add(original); } Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/util/GenericsUtil.java URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/util/GenericsUtil.java?rev=1861905&r1=1861904&r2=1861905&view=diff ============================================================================== --- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/util/GenericsUtil.java (original) +++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/util/GenericsUtil.java Sun Jun 23 09:10:31 2019 @@ -33,6 +33,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import org.apache.webbeans.config.OwbGenericArrayTypeImpl; @@ -45,11 +46,15 @@ import org.apache.webbeans.config.OwbWil */ public final class GenericsUtil { - public static boolean satisfiesDependency(boolean isDelegateOrEvent, boolean isProducer, Type injectionPointType, Type beanType) + + private static final int MAX_GENERIC_LOOPS = 4; // todo: config? it is already crazy :s + + public static boolean satisfiesDependency(boolean isDelegateOrEvent, boolean isProducer, Type injectionPointType, Type beanType, + Map visited) { if (beanType instanceof TypeVariable || beanType instanceof WildcardType || beanType instanceof GenericArrayType) { - return isAssignableFrom(isDelegateOrEvent, isProducer, injectionPointType, beanType); + return isAssignableFrom(isDelegateOrEvent, isProducer, injectionPointType, beanType, visited); } else { @@ -58,18 +63,19 @@ public final class GenericsUtil if (ClassUtil.isSame(injectionPointRawType, beanRawType)) { - return isAssignableFrom(isDelegateOrEvent, isProducer, injectionPointType, beanType); + return isAssignableFrom(isDelegateOrEvent, isProducer, injectionPointType, beanType, visited); } } return false; } - public static boolean satisfiesDependencyRaw(boolean isDelegateOrEvent, boolean isProducer, Type injectionPointType, Type beanType) + public static boolean satisfiesDependencyRaw(boolean isDelegateOrEvent, boolean isProducer, Type injectionPointType, Type beanType, + Map visited) { if (beanType instanceof TypeVariable || beanType instanceof WildcardType || beanType instanceof GenericArrayType) { - return isAssignableFrom(isDelegateOrEvent, isProducer, injectionPointType, beanType); + return isAssignableFrom(isDelegateOrEvent, isProducer, injectionPointType, beanType, visited); } else { @@ -78,7 +84,7 @@ public final class GenericsUtil if (ClassUtil.isSame(injectionPointRawType, beanRawType)) { - return isAssignableFrom(isDelegateOrEvent, isProducer, injectionPointRawType, beanRawType); + return isAssignableFrom(isDelegateOrEvent, isProducer, injectionPointRawType, beanRawType, visited); } else { @@ -110,36 +116,35 @@ public final class GenericsUtil /** * 5.2.3 and 5.2.4 */ - public static boolean isAssignableFrom(boolean isDelegateOrEvent, boolean isProducer, Type requiredType, Type beanType) + public static boolean isAssignableFrom(boolean isDelegateOrEvent, boolean isProducer, Type requiredType, Type beanType, + Map visited) { if (requiredType instanceof Class) { - return isAssignableFrom(isDelegateOrEvent, (Class)requiredType, beanType); + return isAssignableFrom(isDelegateOrEvent, (Class)requiredType, beanType, visited); } else if (requiredType instanceof ParameterizedType) { - return isAssignableFrom(isDelegateOrEvent, isProducer, (ParameterizedType)requiredType, beanType); + return isAssignableFrom(isDelegateOrEvent, isProducer, (ParameterizedType)requiredType, beanType, visited); } else if (requiredType instanceof TypeVariable) { - return isAssignableFrom(isDelegateOrEvent, (TypeVariable)requiredType, beanType); + return isAssignableFrom(isDelegateOrEvent, (TypeVariable)requiredType, beanType, visited); } else if (requiredType instanceof GenericArrayType) { return Class.class.isInstance(beanType) && Class.class.cast(beanType).isArray() - && isAssignableFrom(isDelegateOrEvent, (GenericArrayType)requiredType, beanType); + && isAssignableFrom(isDelegateOrEvent, (GenericArrayType)requiredType, beanType, visited); } else if (requiredType instanceof WildcardType) { - return isAssignableFrom(isDelegateOrEvent, (WildcardType)requiredType, beanType); - } - else - { - throw new IllegalArgumentException("Unsupported type " + requiredType.getClass()); + return isAssignableFrom(isDelegateOrEvent, (WildcardType)requiredType, beanType, visited); } + throw new IllegalArgumentException("Unsupported type " + requiredType.getClass()); } - private static boolean isAssignableFrom(boolean isDelegateOrEvent, Class injectionPointType, Type beanType) + private static boolean isAssignableFrom(boolean isDelegateOrEvent, Class injectionPointType, Type beanType, + Map visited) { if (beanType instanceof Class) { @@ -147,19 +152,19 @@ public final class GenericsUtil } else if (beanType instanceof TypeVariable) { - return isAssignableFrom(isDelegateOrEvent, injectionPointType, (TypeVariable)beanType); + return isAssignableFrom(isDelegateOrEvent, injectionPointType, (TypeVariable)beanType, visited); } else if (beanType instanceof ParameterizedType) { - return isAssignableFrom(isDelegateOrEvent, injectionPointType, (ParameterizedType)beanType); + return isAssignableFrom(isDelegateOrEvent, injectionPointType, (ParameterizedType)beanType, visited); } else if (beanType instanceof GenericArrayType) { - return isAssignableFrom(isDelegateOrEvent, injectionPointType, (GenericArrayType)beanType); + return isAssignableFrom(isDelegateOrEvent, injectionPointType, (GenericArrayType)beanType, visited); } else if (beanType instanceof WildcardType) { - return isAssignableFrom(isDelegateOrEvent, (Type)injectionPointType, (WildcardType)beanType); + return isAssignableFrom(isDelegateOrEvent, (Type)injectionPointType, (WildcardType)beanType, visited); } else { @@ -172,11 +177,12 @@ public final class GenericsUtil return ClassUtil.isClassAssignableFrom(injectionPointType, beanType); } - private static boolean isAssignableFrom(boolean isDelegateOrEvent, Class injectionPointType, TypeVariable beanType) + private static boolean isAssignableFrom(boolean isDelegateOrEvent, Class injectionPointType, TypeVariable beanType, + Map visited) { for (Type bounds: beanType.getBounds()) { - if (isAssignableFrom(isDelegateOrEvent, injectionPointType, bounds)) + if (isAssignableFrom(isDelegateOrEvent, injectionPointType, bounds, visited)) { return true; } @@ -188,7 +194,8 @@ public final class GenericsUtil * CDI Spec. 5.2.4: "A parameterized bean type is considered assignable to a raw required type * if the raw types are identical and all type parameters of the bean type are either unbounded type variables or java.lang.Object." */ - private static boolean isAssignableFrom(boolean isDelegateOrEvent, Class injectionPointType, ParameterizedType beanType) + private static boolean isAssignableFrom(boolean isDelegateOrEvent, Class injectionPointType, ParameterizedType beanType, + Map visited) { if (beanType.getRawType() != injectionPointType) { @@ -199,7 +206,7 @@ public final class GenericsUtil { // for delegate and events we match 'in reverse' kind off // @Observes ProcessInjectionPoint does also match Instance - return isAssignableFrom(true, injectionPointType, beanType.getRawType()); + return isAssignableFrom(true, injectionPointType, beanType.getRawType(), visited); } for (Type typeArgument: beanType.getActualTypeArguments()) @@ -224,23 +231,29 @@ public final class GenericsUtil return true; } - private static boolean isAssignableFrom(boolean isDelegateOrEvent, Class injectionPointType, GenericArrayType beanType) + private static boolean isAssignableFrom(boolean isDelegateOrEvent, Class injectionPointType, GenericArrayType beanType, + Map visited) { - return injectionPointType.isArray() && isAssignableFrom(isDelegateOrEvent, injectionPointType.getComponentType(), beanType.getGenericComponentType()); + return injectionPointType.isArray() && isAssignableFrom(isDelegateOrEvent, injectionPointType.getComponentType(), beanType.getGenericComponentType(), visited); } - private static boolean isAssignableFrom(boolean isDelegateOrEvent, Type injectionPointType, WildcardType beanType) + private static boolean isAssignableFrom(boolean isDelegateOrEvent, Type injectionPointType, WildcardType beanType, + Map visited) { + if (isGenericLoop(beanType, visited)) + { + return false; + } for (Type bounds: beanType.getLowerBounds()) { - if (!isAssignableFrom(isDelegateOrEvent, false, bounds, injectionPointType)) + if (!isAssignableFrom(isDelegateOrEvent, false, bounds, injectionPointType, visited)) { return false; } } for (Type bounds: beanType.getUpperBounds()) { - if (isAssignableFrom(isDelegateOrEvent, false, injectionPointType, bounds)) + if (isAssignableFrom(isDelegateOrEvent, false, injectionPointType, bounds, visited)) { return true; } @@ -248,23 +261,29 @@ public final class GenericsUtil return false; } - private static boolean isAssignableFrom(boolean isDelegateOrEvent, boolean isProducer, ParameterizedType injectionPointType, Type beanType) + private static boolean isGenericLoop(Type beanType, Map visited) + { + return visited.compute(beanType, (type, integer) -> integer == null ? 1 : (integer + 1)) > MAX_GENERIC_LOOPS; + } + + private static boolean isAssignableFrom(boolean isDelegateOrEvent, boolean isProducer, ParameterizedType injectionPointType, Type beanType, + Map visited) { if (beanType instanceof Class) { - return isAssignableFrom(isDelegateOrEvent, isProducer, injectionPointType, (Class)beanType); + return isAssignableFrom(isDelegateOrEvent, isProducer, injectionPointType, (Class)beanType, visited); } else if (beanType instanceof TypeVariable) { - return isAssignableFrom(isDelegateOrEvent, isProducer, injectionPointType, (TypeVariable)beanType); + return isAssignableFrom(isDelegateOrEvent, isProducer, injectionPointType, (TypeVariable)beanType, visited); } else if (beanType instanceof ParameterizedType) { - return isAssignableFrom(isDelegateOrEvent, injectionPointType, (ParameterizedType)beanType); + return isAssignableFrom(isDelegateOrEvent, injectionPointType, (ParameterizedType)beanType, visited); } else if (beanType instanceof WildcardType) { - return isAssignableFrom(isDelegateOrEvent, injectionPointType, (WildcardType)beanType); + return isAssignableFrom(isDelegateOrEvent, injectionPointType, (WildcardType)beanType, visited); } else if (beanType instanceof GenericArrayType) { @@ -276,7 +295,8 @@ public final class GenericsUtil } } - private static boolean isAssignableFrom(boolean isDelegateOrEvent, boolean isProducer, ParameterizedType injectionPointType, Class beanType) + private static boolean isAssignableFrom(boolean isDelegateOrEvent, boolean isProducer, ParameterizedType injectionPointType, Class beanType, + Map visited) { Class rawInjectionPointType = getRawType(injectionPointType); if (rawInjectionPointType.equals(beanType)) @@ -300,13 +320,13 @@ public final class GenericsUtil { return false; } - if (beanType.getSuperclass() != null && isAssignableFrom(isDelegateOrEvent, isProducer, injectionPointType, beanType.getGenericSuperclass())) + if (beanType.getSuperclass() != null && isAssignableFrom(isDelegateOrEvent, isProducer, injectionPointType, beanType.getGenericSuperclass(), visited)) { return true; } for (Type genericInterface: beanType.getGenericInterfaces()) { - if (isAssignableFrom(isDelegateOrEvent, isProducer, injectionPointType, genericInterface)) + if (isAssignableFrom(isDelegateOrEvent, isProducer, injectionPointType, genericInterface, visited)) { return true; } @@ -314,7 +334,8 @@ public final class GenericsUtil return false; } - private static boolean isAssignableFrom(boolean isDelegateOrEvent, boolean isProducer, ParameterizedType injectionPointType, TypeVariable beanType) + private static boolean isAssignableFrom(boolean isDelegateOrEvent, boolean isProducer, ParameterizedType injectionPointType, TypeVariable beanType, + Map visited) { Type[] types = beanType.getBounds(); if (isNotBound(types)) @@ -323,7 +344,7 @@ public final class GenericsUtil } for (Type bounds: types) { - if (isAssignableFrom(isDelegateOrEvent, isProducer, injectionPointType, bounds)) + if (isAssignableFrom(isDelegateOrEvent, isProducer, injectionPointType, bounds, visited)) { return true; } @@ -334,7 +355,8 @@ public final class GenericsUtil /** * CDI Spec. 5.2.4 */ - private static boolean isAssignableFrom(boolean isDelegateOrEvent, ParameterizedType injectionPointType, ParameterizedType beanType) + private static boolean isAssignableFrom(boolean isDelegateOrEvent, ParameterizedType injectionPointType, ParameterizedType beanType, + Map visited) { if (injectionPointType.getRawType() != beanType.getRawType()) { @@ -360,7 +382,7 @@ public final class GenericsUtil { for (Type upperBound : bounds) { - if (!isAssignableFrom(true, false, upperBound, injectionPointTypeArgument)) + if (!isAssignableFrom(true, false, upperBound, injectionPointTypeArgument, visited)) { return false; } @@ -377,7 +399,7 @@ public final class GenericsUtil return injectionPointTypeArgument.equals(beanTypeArgument); } - else if (!isAssignableFrom(isDelegateOrEvent, false, injectionPointTypeArgument, beanTypeArgument)) + else if (!isAssignableFrom(isDelegateOrEvent, false, injectionPointTypeArgument, beanTypeArgument, visited)) { return false; } @@ -390,11 +412,16 @@ public final class GenericsUtil return bounds == null || bounds.length == 0 || (bounds.length == 1 && Object.class == bounds[0]); } - private static boolean isAssignableFrom(boolean isDelegateOrEvent, TypeVariable injectionPointType, Type beanType) + private static boolean isAssignableFrom(boolean isDelegateOrEvent, TypeVariable injectionPointType, Type beanType, + Map visited) { + if (isGenericLoop(beanType, visited)) + { + return false; // looping type so not resolvable + } for (Type bounds: injectionPointType.getBounds()) { - if (!isAssignableFrom(isDelegateOrEvent, false, bounds, beanType)) + if (!isAssignableFrom(isDelegateOrEvent, false, bounds, beanType, visited)) { return false; } @@ -403,7 +430,8 @@ public final class GenericsUtil } // rules are a bit different when in an array so we handle ParameterizedType manually (not reusing isAssignableFrom) - private static boolean isAssignableFrom(boolean isDelegateOrEvent, GenericArrayType injectionPointType, Type beanType) + private static boolean isAssignableFrom(boolean isDelegateOrEvent, GenericArrayType injectionPointType, Type beanType, + Map visited) { Type genericComponentType = injectionPointType.getGenericComponentType(); Class componentType = Class.class.cast(beanType).getComponentType(); @@ -413,20 +441,21 @@ public final class GenericsUtil } if (ParameterizedType.class.isInstance(genericComponentType)) { - return isAssignableFrom(isDelegateOrEvent, false, ParameterizedType.class.cast(genericComponentType).getRawType(), componentType); + return isAssignableFrom(isDelegateOrEvent, false, ParameterizedType.class.cast(genericComponentType).getRawType(), componentType, visited); } - return isAssignableFrom(isDelegateOrEvent, false, genericComponentType, componentType); + return isAssignableFrom(isDelegateOrEvent, false, genericComponentType, componentType, visited); } - private static boolean isAssignableFrom(boolean isDelegateOrEvent, WildcardType injectionPointType, Type beanType) + private static boolean isAssignableFrom(boolean isDelegateOrEvent, WildcardType injectionPointType, Type beanType, + Map visited) { if (beanType instanceof TypeVariable) { - return isAssignableFrom(isDelegateOrEvent, injectionPointType, (TypeVariable)beanType); + return isAssignableFrom(isDelegateOrEvent, injectionPointType, (TypeVariable)beanType, visited); } for (Type bounds: injectionPointType.getLowerBounds()) { - if (!isAssignableFrom(isDelegateOrEvent, false, beanType, bounds)) + if (!isAssignableFrom(isDelegateOrEvent, false, beanType, bounds, visited)) { return false; } @@ -437,7 +466,7 @@ public final class GenericsUtil boolean isAssignable = false; for (Type beanSupertype: beanTypeClosure) { - if (isAssignableFrom(isDelegateOrEvent, false, bounds, beanSupertype) + if (isAssignableFrom(isDelegateOrEvent, false, bounds, beanSupertype, visited) || (Class.class.isInstance(bounds) && ParameterizedType.class.isInstance(beanSupertype) && bounds == ParameterizedType.class.cast(beanSupertype).getRawType())) @@ -457,13 +486,14 @@ public final class GenericsUtil /** * CDI 1.1 Spec. 5.2.4, third bullet point */ - private static boolean isAssignableFrom(boolean isDelegateOrEvent, WildcardType injectionPointType, TypeVariable beanType) + private static boolean isAssignableFrom(boolean isDelegateOrEvent, WildcardType injectionPointType, TypeVariable beanType, + Map visited) { for (Type upperBound: injectionPointType.getUpperBounds()) { for (Type bound: beanType.getBounds()) { - if (!isAssignableFrom(isDelegateOrEvent, false, upperBound, bound) && !isAssignableFrom(isDelegateOrEvent, false, bound, upperBound)) + if (!isAssignableFrom(isDelegateOrEvent, false, upperBound, bound, visited) && !isAssignableFrom(isDelegateOrEvent, false, bound, upperBound, visited)) { return false; } @@ -473,7 +503,7 @@ public final class GenericsUtil { for (Type bound: beanType.getBounds()) { - if (!isAssignableFrom(isDelegateOrEvent, false, bound, lowerBound)) + if (!isAssignableFrom(isDelegateOrEvent, false, bound, lowerBound, visited)) { return false; } Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/util/WebBeansUtil.java URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/util/WebBeansUtil.java?rev=1861905&r1=1861904&r2=1861905&view=diff ============================================================================== --- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/util/WebBeansUtil.java (original) +++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/util/WebBeansUtil.java Sun Jun 23 09:10:31 2019 @@ -151,6 +151,7 @@ import java.lang.reflect.WildcardType; import java.util.Arrays; import java.util.Collections; import java.util.EnumSet; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -1471,7 +1472,8 @@ public final class WebBeansUtil rawType.equals(Interceptor.class)) { Type[] types = ClassUtil.getActualTypeArguments(injectionPoint.getType()); - if (types.length != 1 || !GenericsUtil.isAssignableFrom(false, AbstractProducerBean.class.isInstance(bean), bean.getBeanClass(), types[0])) + if (types.length != 1 || !GenericsUtil.isAssignableFrom( + false, AbstractProducerBean.class.isInstance(bean), bean.getBeanClass(), types[0], new HashMap<>())) { throw new WebBeansConfigurationException("injected bean parameter must be " + rawType); } @@ -1720,7 +1722,8 @@ public final class WebBeansUtil Class beanClass = AbstractOwbBean.class.isInstance(injectionPointBean) ? AbstractOwbBean.class.cast(injectionPointBean).getReturnType() : injectionPointBean.getBeanClass(); Type beanType = pt.getActualTypeArguments()[0]; - if (!GenericsUtil.isAssignableFrom(false, AbstractProducerBean.class.isInstance(bean), beanClass, beanType)) + if (!GenericsUtil.isAssignableFrom( + false, AbstractProducerBean.class.isInstance(bean), beanClass, beanType, new HashMap<>())) { throw new WebBeansConfigurationException("@Inject Bean can only be done in X, found " + beanType + " and " + beanClass); } Modified: openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/unittests/inject/parametrized/GenericClassTest.java URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/unittests/inject/parametrized/GenericClassTest.java?rev=1861905&r1=1861904&r2=1861905&view=diff ============================================================================== --- openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/unittests/inject/parametrized/GenericClassTest.java (original) +++ openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/unittests/inject/parametrized/GenericClassTest.java Sun Jun 23 09:10:31 2019 @@ -20,6 +20,7 @@ package org.apache.webbeans.test.unittes import java.lang.reflect.Field; import java.lang.reflect.Type; +import java.util.HashMap; import org.apache.webbeans.test.injection.generics.zoo.Horse; import org.apache.webbeans.test.injection.generics.zoo.HorseStable; @@ -44,10 +45,10 @@ public class GenericClassTest Field check22Bound = Dao.class.getField("check22WithBound"); Field check4 = WithTypeVariable.class.getField("check4"); - Assert.assertFalse(GenericsUtil.satisfiesDependency(false, false, raw.getGenericType(), t.getGenericType())); - Assert.assertTrue(GenericsUtil.satisfiesDependency(false, false, check4.getGenericType(), t.getGenericType())); - Assert.assertTrue(GenericsUtil.satisfiesDependency(false, false, check22.getGenericType(), t.getGenericType())); - Assert.assertTrue(GenericsUtil.satisfiesDependency(false, false, check22Bound.getGenericType(), t.getGenericType())); + Assert.assertFalse(GenericsUtil.satisfiesDependency(false, false, raw.getGenericType(), t.getGenericType(), new HashMap<>())); + Assert.assertTrue(GenericsUtil.satisfiesDependency(false, false, check4.getGenericType(), t.getGenericType(), new HashMap<>())); + Assert.assertTrue(GenericsUtil.satisfiesDependency(false, false, check22.getGenericType(), t.getGenericType(), new HashMap<>())); + Assert.assertTrue(GenericsUtil.satisfiesDependency(false, false, check22Bound.getGenericType(), t.getGenericType(), new HashMap<>())); } @Test @@ -59,8 +60,8 @@ public class GenericClassTest Field f4 = UserDao.class.getField("field4"); - Assert.assertTrue(GenericsUtil.satisfiesDependency(false, false, f3.getGenericType(), f1.getGenericType())); - Assert.assertTrue(GenericsUtil.satisfiesDependency(false, false, f4.getGenericType(), f1.getGenericType())); + Assert.assertTrue(GenericsUtil.satisfiesDependency(false, false, f3.getGenericType(), f1.getGenericType(), new HashMap<>())); + Assert.assertTrue(GenericsUtil.satisfiesDependency(false, false, f4.getGenericType(), f1.getGenericType(), new HashMap<>())); } @Test @@ -74,8 +75,8 @@ public class GenericClassTest Type pigStableType = this.getClass().getDeclaredField("pigStable").getType().getGenericSuperclass(); Type horseStableType = this.getClass().getDeclaredField("horseStable").getType().getGenericSuperclass(); - Assert.assertTrue(GenericsUtil.satisfiesDependency(false, false, horseStableType, parameterizedHorseStableType)); - Assert.assertTrue(GenericsUtil.satisfiesDependency(false, false, parameterizedPigStableType, pigStableType)); + Assert.assertTrue(GenericsUtil.satisfiesDependency(false, false, horseStableType, parameterizedHorseStableType, new HashMap<>())); + Assert.assertTrue(GenericsUtil.satisfiesDependency(false, false, parameterizedPigStableType, pigStableType, new HashMap<>())); } // fields for {@link #testStable} private Stable parameterizedHorseStable; @@ -91,8 +92,8 @@ public class GenericClassTest Type parameterizedHorseStableType = this.getClass().getDeclaredField("parameterizedHorseStable").getGenericType(); Type stableProducerMethodType = this.getClass().getDeclaredMethod("stableProducer").getGenericReturnType(); - Assert.assertTrue(GenericsUtil.satisfiesDependency(false, false, parameterizedPigStableType, stableProducerMethodType)); - Assert.assertTrue(GenericsUtil.satisfiesDependency(false, false, parameterizedHorseStableType, stableProducerMethodType)); + Assert.assertTrue(GenericsUtil.satisfiesDependency(false, false, parameterizedPigStableType, stableProducerMethodType, new HashMap<>())); + Assert.assertTrue(GenericsUtil.satisfiesDependency(false, false, parameterizedHorseStableType, stableProducerMethodType, new HashMap<>())); } // method and field for {@link #testGenericProducerType} private Stable stableProducer() Modified: openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/util/GenericsUtilTest.java URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/util/GenericsUtilTest.java?rev=1861905&r1=1861904&r2=1861905&view=diff ============================================================================== --- openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/util/GenericsUtilTest.java (original) +++ openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/util/GenericsUtilTest.java Sun Jun 23 09:10:31 2019 @@ -20,8 +20,11 @@ package org.apache.webbeans.test.util; import static java.util.Arrays.asList; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import java.lang.annotation.Annotation; +import java.lang.reflect.AnnotatedType; import java.lang.reflect.Field; import java.lang.reflect.GenericArrayType; import java.lang.reflect.Method; @@ -30,6 +33,8 @@ import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; import java.util.Set; import org.apache.webbeans.config.OwbParametrizedTypeImpl; @@ -87,6 +92,100 @@ public class GenericsUtilTest { Assert.assertFalse(GenericsUtil.containsWildcardType(GenericObject.class.getMethod("getObject").getGenericReturnType())); } + @Test + public void genericsLoop() + { + final ParameterizedType injectionPointType = new OwbParametrizedTypeImpl(null, GenericFoo.class, Long.class); + final TypeVariable> t = new TypeVariable>() { + @Override + public Type[] getBounds() { + final TypeVariable ref = this; + return new Type[]{ + new OwbParametrizedTypeImpl(null, Comparable.class, new TypeVariable>() { + @Override + public T getAnnotation(Class annotationClass) + { + return null; + } + + @Override + public Annotation[] getAnnotations() + { + return new Annotation[0]; + } + + @Override + public Annotation[] getDeclaredAnnotations() + { + return new Annotation[0]; + } + + @Override + public Type[] getBounds() + { + return new Type[] { new OwbParametrizedTypeImpl(null, Comparable.class, ref) }; + } + + @Override + public Class getGenericDeclaration() { + return GenericFoo.class; + } + + @Override + public String getName() + { + return "T"; + } + + @Override + public AnnotatedType[] getAnnotatedBounds() + { + return new AnnotatedType[0]; + } + }) + }; + } + + @Override + public Class getGenericDeclaration() + { + return GenericFoo.class; + } + + @Override + public String getName() + { + return "T"; + } + + @Override + public AnnotatedType[] getAnnotatedBounds() + { + return new AnnotatedType[0]; + } + + @Override + public T getAnnotation(Class annotationClass) + { + return null; + } + + @Override + public Annotation[] getAnnotations() + { + return new Annotation[0]; + } + + @Override + public Annotation[] getDeclaredAnnotations() + { + return new Annotation[0]; + } + }; + final ParameterizedType beanType = new OwbParametrizedTypeImpl(null, GenericFoo.class, t); + assertFalse(GenericsUtil.satisfiesDependency(false, false, injectionPointType, beanType, new HashMap<>())); + } + public static abstract class AbstractObject { @@ -180,4 +279,23 @@ public class GenericsUtilTest { return this; } } + + public interface GenericFoo> + { + T someMethod(); + } + + public static class FooImpl> implements GenericFoo + { + @Override + public T someMethod() + { + return null; + } + } + + public static class Bar + { + GenericFoo foo; + } }