You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by gn...@apache.org on 2016/03/09 16:22:15 UTC

svn commit: r1734264 - in /aries/trunk/blueprint/blueprint-core/src: main/java/org/apache/aries/blueprint/container/ test/java/org/apache/aries/blueprint/ test/java/org/apache/aries/blueprint/container/ test/java/org/apache/aries/blueprint/pojos/ test/...

Author: gnodet
Date: Wed Mar  9 15:22:15 2016
New Revision: 1734264

URL: http://svn.apache.org/viewvc?rev=1734264&view=rev
Log:
[ARIES-1500] Fix some problems with conversions of wildcard types

Added:
    aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/pojos/PojoGenerics2.java
Modified:
    aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/AggregateConverter.java
    aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/GenericType.java
    aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/WiringTest.java
    aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/AggregateConverterTest.java
    aries/trunk/blueprint/blueprint-core/src/test/resources/test-generics.xml

Modified: aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/AggregateConverter.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/AggregateConverter.java?rev=1734264&r1=1734263&r2=1734264&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/AggregateConverter.java (original)
+++ aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/AggregateConverter.java Wed Mar  9 15:22:15 2016
@@ -42,6 +42,7 @@ import java.util.concurrent.atomic.Atomi
 import java.util.regex.Pattern;
 
 import org.apache.aries.blueprint.container.BeanRecipe.UnwrapperedBeanHolder;
+import org.apache.aries.blueprint.container.GenericType.BoundType;
 import org.apache.aries.blueprint.di.CollectionRecipe;
 import org.apache.aries.blueprint.di.MapRecipe;
 import org.apache.aries.blueprint.services.ExtendedBlueprintContainer;
@@ -460,6 +461,22 @@ public class AggregateConverter implemen
         if (from.equals(to)) {
             return true;
         }
+        if (from.getRawClass() == to.getRawClass()) {
+            if (from.size() == to.size()) {
+                boolean ok = true;
+                for (int i = 0; i < from.size(); i++) {
+                    ReifiedType tf = from.getActualTypeArgument(i);
+                    ReifiedType tt = to.getActualTypeArgument(i);
+                    if (!isWildcardCompatible(tf, tt)) {
+                        ok = false;
+                        break;
+                    }
+                }
+                if (ok) {
+                    return true;
+                }
+            }
+        }
         Type t = from.getRawClass().getGenericSuperclass();
         if (t != null && isTypeAssignable(new GenericType(t), to)) {
             return true;
@@ -472,6 +489,18 @@ public class AggregateConverter implemen
         return false;
     }
 
+    private static boolean isWildcardCompatible(ReifiedType from, ReifiedType to) {
+        BoundType fromBoundType = GenericType.boundType(from);
+        BoundType toBoundType = GenericType.boundType(to);
+        if (toBoundType == BoundType.Extends) {
+            return fromBoundType != BoundType.Super && isTypeAssignable(from, GenericType.bound(to));
+        } else if (toBoundType == BoundType.Super) {
+            return fromBoundType != BoundType.Extends && isTypeAssignable(GenericType.bound(to), from);
+        } else {
+            return fromBoundType == BoundType.Exact && GenericType.bound(from).equals(GenericType.bound(to));
+        }
+    }
+
     private static Class unwrap(Class c) {
         Class u = primitives.get(c);
         return u != null ? u : c;

Modified: aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/GenericType.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/GenericType.java?rev=1734264&r1=1734263&r2=1734264&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/GenericType.java (original)
+++ aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/GenericType.java Wed Mar  9 15:22:15 2016
@@ -56,15 +56,27 @@ public class GenericType extends Reified
         primitiveClasses.put("boolean", boolean.class);
     }
 
+    enum BoundType {
+        Exact,
+        Extends,
+        Super
+    }
+
     private GenericType[] parameters;
+    private BoundType boundType;
 
 	public GenericType(Type type) {
-		this(getConcreteClass(type), parametersOf(type));
+		this(getConcreteClass(type), boundType(type), parametersOf(type));
 	}
 
     public GenericType(Class clazz, GenericType... parameters) {
+        this(clazz, BoundType.Exact, parameters);
+    }
+
+    public GenericType(Class clazz, BoundType boundType, GenericType... parameters) {
         super(clazz);
         this.parameters = parameters;
+        this.boundType = boundType;
     }
 
     public static GenericType parse(String rawType, final Object loader) throws ClassNotFoundException, IllegalArgumentException {
@@ -133,6 +145,12 @@ public class GenericType extends Reified
 
     @Override
     public String toString() {
+        StringBuilder sb = new StringBuilder();
+        if (boundType == BoundType.Extends) {
+            sb.append("? extends ");
+        } else if (boundType == BoundType.Super) {
+            sb.append("? super ");
+        }
         Class cl = getRawClass();
         if (cl.isArray()) {
             if (parameters.length > 0) {
@@ -141,9 +159,8 @@ public class GenericType extends Reified
                 return cl.getComponentType().getName() + "[]";
             }
         }
+        sb.append(cl.getName());
         if (parameters.length > 0) {
-            StringBuilder sb = new StringBuilder();
-            sb.append(cl.getName());    
             sb.append("<");
             for (int i = 0; i < parameters.length; i++) {
                 if (i > 0) {
@@ -152,9 +169,8 @@ public class GenericType extends Reified
                 sb.append(parameters[i].toString());
             }
             sb.append(">");   
-            return sb.toString();
         }
-        return cl.getName();
+        return sb.toString();
     }
 
     public boolean equals(Object object) {
@@ -165,6 +181,9 @@ public class GenericType extends Reified
         if (getRawClass() != other.getRawClass()) {
             return false;
         }
+        if (boundType != other.boundType) {
+            return false;
+        }
         if (parameters == null) {
             return (other.parameters == null);
         } else {
@@ -182,7 +201,33 @@ public class GenericType extends Reified
             return true;
         }
     }
-    
+
+    static ReifiedType bound(ReifiedType type) {
+        if (type instanceof GenericType
+                && ((GenericType) type).boundType != BoundType.Exact) {
+            GenericType t = (GenericType) type;
+            return new GenericType(t.getRawClass(), BoundType.Exact, t.parameters);
+        }
+        return type;
+    }
+
+    static BoundType boundType(ReifiedType type) {
+        if (type instanceof GenericType) {
+            return ((GenericType) type).boundType;
+        } else {
+            return BoundType.Exact;
+        }
+    }
+
+    static BoundType boundType(Type type) {
+        if (type instanceof WildcardType) {
+            WildcardType wct = (WildcardType) type;
+            return wct.getLowerBounds().length == 0
+                    ? BoundType.Extends : BoundType.Super;
+        }
+        return BoundType.Exact;
+    }
+
     static GenericType[] parametersOf(Type type) {
 		if (type instanceof Class) {
 		    Class clazz = (Class) type;

Modified: aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/WiringTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/WiringTest.java?rev=1734264&r1=1734263&r2=1734264&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/WiringTest.java (original)
+++ aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/WiringTest.java Wed Mar  9 15:22:15 2016
@@ -18,6 +18,7 @@
  */
 package org.apache.aries.blueprint;
 
+import java.lang.reflect.Constructor;
 import java.math.BigInteger;
 import java.net.URI;
 import java.util.ArrayList;
@@ -36,7 +37,9 @@ import java.util.TimeZone;
 import junit.framework.Assert;
 
 import org.apache.aries.blueprint.CallbackTracker.Callback;
+import org.apache.aries.blueprint.container.AggregateConverter;
 import org.apache.aries.blueprint.container.BlueprintRepository;
+import org.apache.aries.blueprint.container.GenericType;
 import org.apache.aries.blueprint.container.ServiceRecipe;
 import org.apache.aries.blueprint.di.CircularDependencyException;
 import org.apache.aries.blueprint.di.ExecutionContext;
@@ -52,6 +55,10 @@ import org.apache.aries.blueprint.pojos.
 import org.apache.aries.blueprint.pojos.PojoA;
 import org.apache.aries.blueprint.pojos.PojoB;
 import org.apache.aries.blueprint.pojos.PojoGenerics;
+import org.apache.aries.blueprint.pojos.PojoGenerics2.MyClass;
+import org.apache.aries.blueprint.pojos.PojoGenerics2.MyObject;
+import org.apache.aries.blueprint.pojos.PojoGenerics2.Tata;
+import org.apache.aries.blueprint.pojos.PojoGenerics2.Toto;
 import org.apache.aries.blueprint.pojos.PojoListener;
 import org.apache.aries.blueprint.pojos.PojoRecursive;
 import org.apache.aries.blueprint.pojos.Primavera;
@@ -399,6 +406,12 @@ public class WiringTest extends Abstract
        assertEquals(map, ((Multiple)obj).getProperties());
    }
 
+    public void testGenerics2() throws Exception {
+        ComponentDefinitionRegistryImpl registry = parse("/test-generics.xml");
+        Repository repository = new TestBlueprintContainer(registry).getRepository();
+        repository.create("gen2");
+    }
+
     public void testGenerics() throws Exception {
         ComponentDefinitionRegistryImpl registry = parse("/test-generics.xml");
         Repository repository = new TestBlueprintContainer(registry).getRepository();

Modified: aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/AggregateConverterTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/AggregateConverterTest.java?rev=1734264&r1=1734263&r2=1734264&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/AggregateConverterTest.java (original)
+++ aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/AggregateConverterTest.java Wed Mar  9 15:22:15 2016
@@ -19,6 +19,7 @@
 package org.apache.aries.blueprint.container;
 
 import java.io.ByteArrayOutputStream;
+import java.lang.reflect.Constructor;
 import java.math.BigInteger;
 import java.net.URI;
 import java.net.URL;
@@ -33,6 +34,10 @@ import java.util.Properties;
 
 import junit.framework.TestCase;
 import org.apache.aries.blueprint.TestBlueprintContainer;
+import org.apache.aries.blueprint.pojos.PojoGenerics2.MyClass;
+import org.apache.aries.blueprint.pojos.PojoGenerics2.MyObject;
+import org.apache.aries.blueprint.pojos.PojoGenerics2.Tata;
+import org.apache.aries.blueprint.pojos.PojoGenerics2.Toto;
 import org.osgi.service.blueprint.container.ReifiedType;
 import org.osgi.service.blueprint.container.Converter;
 
@@ -193,6 +198,14 @@ public class AggregateConverterTest exte
         assertNull(result);
     }
 
+    public void testGenericWilcard() throws Exception {
+        Constructor cns = MyClass.class.getConstructor(MyObject.class);
+        assertTrue(AggregateConverter.isAssignable(new Toto(), new GenericType(cns.getGenericParameterTypes()[0])));
+
+        cns = Tata.class.getConstructor(MyObject.class);
+        assertTrue(AggregateConverter.isAssignable(new Toto(), new GenericType(cns.getGenericParameterTypes()[0])));
+    }
+
     public void testGenericAssignable() throws Exception {
         AggregateConverter s = new AggregateConverter(new TestBlueprintContainer(null));
 

Added: aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/pojos/PojoGenerics2.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/pojos/PojoGenerics2.java?rev=1734264&view=auto
==============================================================================
--- aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/pojos/PojoGenerics2.java (added)
+++ aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/pojos/PojoGenerics2.java Wed Mar  9 15:22:15 2016
@@ -0,0 +1,51 @@
+/*
+ * 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.aries.blueprint.pojos;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class PojoGenerics2 {
+
+    public static class MyClass<T> {
+
+        private final MyObject<? extends T> object;
+
+        public MyClass(final MyObject<? extends T> object)
+        {
+            this.object = object;
+        }
+    }
+
+    public static class Tata extends MyClass<String> {
+
+        public Tata(MyObject<? extends String> object) {
+            super(object);
+        }
+
+    }
+
+    public static class MyObject<T> {
+    }
+
+    public static class Toto extends MyObject<String> {
+    }
+
+}

Modified: aries/trunk/blueprint/blueprint-core/src/test/resources/test-generics.xml
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/test/resources/test-generics.xml?rev=1734264&r1=1734263&r2=1734264&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-core/src/test/resources/test-generics.xml (original)
+++ aries/trunk/blueprint/blueprint-core/src/test/resources/test-generics.xml Wed Mar  9 15:22:15 2016
@@ -20,6 +20,12 @@
             xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0"
             default-availability="mandatory" >
 
+    <bean id="gen2" class="org.apache.aries.blueprint.pojos.PojoGenerics2$MyClass">
+        <argument>
+            <bean class="org.apache.aries.blueprint.pojos.PojoGenerics2$Toto"/>
+        </argument>
+    </bean>
+
     <bean id="method" class="org.apache.aries.blueprint.pojos.PojoGenerics">
         <property name="list">
             <list>