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 2018/01/30 22:05:18 UTC
svn commit: r1822706 [2/2] - in /aries/trunk/blueprint/blueprint-core/src:
main/java/org/apache/aries/blueprint/container/
main/java/org/apache/aries/blueprint/utils/generics/
test/java/org/apache/aries/blueprint/
test/java/org/apache/aries/blueprint/c...
Added: aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/utils/generics/OwbWildcardTypeImpl.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/utils/generics/OwbWildcardTypeImpl.java?rev=1822706&view=auto
==============================================================================
--- aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/utils/generics/OwbWildcardTypeImpl.java (added)
+++ aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/utils/generics/OwbWildcardTypeImpl.java Tue Jan 30 22:05:17 2018
@@ -0,0 +1,103 @@
+/*
+ * 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.utils.generics;
+
+import java.lang.reflect.Type;
+import java.lang.reflect.WildcardType;
+
+public class OwbWildcardTypeImpl implements WildcardType
+{
+
+ private Type[] upperBounds;
+ private Type[] lowerBounds;
+
+ public OwbWildcardTypeImpl(Type[] upperBounds, Type[] lowerBounds)
+ {
+ this.upperBounds = upperBounds.clone();
+ this.lowerBounds = lowerBounds.clone();
+ }
+
+ @Override
+ public Type[] getUpperBounds()
+ {
+ return upperBounds.clone();
+ }
+
+ @Override
+ public Type[] getLowerBounds()
+ {
+ return lowerBounds.clone();
+ }
+
+ public String toString()
+ {
+ StringBuilder buffer = new StringBuilder("?");
+ if (upperBounds.length > 0)
+ {
+ buffer.append(" extends");
+ boolean first = true;
+ for (Type upperBound: upperBounds)
+ {
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ buffer.append(',');
+ }
+ buffer.append(' ');
+ if (upperBound instanceof Class)
+ {
+ buffer.append(((Class<?>)upperBound).getSimpleName());
+ }
+ else
+ {
+ buffer.append(upperBound);
+ }
+ }
+ }
+ if (lowerBounds.length > 0)
+ {
+ buffer.append(" super");
+ boolean first = true;
+ for (Type lowerBound: lowerBounds)
+ {
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ buffer.append(',');
+ }
+ buffer.append(' ');
+ if (lowerBound instanceof Class)
+ {
+ buffer.append(((Class<?>)lowerBound).getSimpleName());
+ }
+ else
+ {
+ buffer.append(lowerBound);
+ }
+ }
+ }
+ return buffer.toString();
+ }
+}
Added: aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/utils/generics/TypeInference.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/utils/generics/TypeInference.java?rev=1822706&view=auto
==============================================================================
--- aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/utils/generics/TypeInference.java (added)
+++ aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/utils/generics/TypeInference.java Tue Jan 30 22:05:17 2018
@@ -0,0 +1,454 @@
+/*
+ * 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.utils.generics;
+
+import org.apache.aries.blueprint.utils.ReflectionUtils;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+public class TypeInference {
+
+ public static class Match<E> {
+ final E e;
+ final List<TypedObject> args;
+ final Map<TypeVariable<?>, Type> inferred;
+ final int score;
+
+ Match(E e, List<TypedObject> args, Map<TypeVariable<?>, Type> inferred, int score) {
+ this.e = e;
+ this.args = args;
+ this.inferred = inferred;
+ this.score = score;
+ }
+
+ public E getMember() {
+ return e;
+ }
+
+ public List<TypedObject> getArgs() {
+ return args;
+ }
+
+ public Map<TypeVariable<?>, Type> getInferred() {
+ return inferred;
+ }
+
+ public int getScore() {
+ return score;
+ }
+ }
+
+ public static class TypedObject {
+ final Type type;
+ final Object value;
+
+ public TypedObject(Type type, Object value) {
+ this.type = type;
+ this.value = value;
+ }
+
+ public Type getType() {
+ return type;
+ }
+
+ public Object getValue() {
+ return value;
+ }
+ }
+
+ public interface Converter {
+ TypedObject convert(TypedObject from, Type to) throws Exception;
+ }
+
+ private interface Executable<T> {
+ T getMember();
+ Type[] getGenericParameterTypes();
+ }
+
+ private static class ConstructorExecutable implements Executable<Constructor<?>> {
+
+ private final Constructor<?> constructor;
+
+ private ConstructorExecutable(Constructor<?> constructor) {
+ this.constructor = constructor;
+ }
+
+ @Override
+ public Constructor<?> getMember() {
+ return constructor;
+ }
+
+ @Override
+ public Type[] getGenericParameterTypes() {
+ return constructor.getGenericParameterTypes();
+ }
+ }
+
+ private static class MethodExecutable implements Executable<Method> {
+
+ private final Method method;
+
+ private MethodExecutable(Method method) {
+ this.method = method;
+ }
+
+ @Override
+ public Method getMember() {
+ return method;
+ }
+
+ @Override
+ public Type[] getGenericParameterTypes() {
+ return method.getGenericParameterTypes();
+ }
+ }
+
+ public static List<Match<Constructor<?>>> findMatchingConstructors(Type clazz, List<TypedObject> args, Converter converter, boolean reorder) {
+ List<Executable<Constructor<?>>> executables = findConstructors(clazz, args.size());
+ return findMatching(executables, args, converter, reorder);
+ }
+
+ public static List<Match<Method>> findMatchingMethods(Type clazz, String name, List<TypedObject> args, Converter converter, boolean reorder) {
+ List<Executable<Method>> executables = findMethods(clazz, name, true, args.size());
+ return findMatching(executables, args, converter, reorder);
+ }
+
+ public static List<Match<Method>> findMatchingStatics(Type clazz, String name, List<TypedObject> args, Converter converter, boolean reorder) {
+ List<Executable<Method>> executables = findMethods(clazz, name, false, args.size());
+ return findMatching(executables, args, converter, reorder);
+ }
+
+ private static List<Method> applyStaticHidingRules(Collection<Method> methods) {
+ List<Method> result = new ArrayList<Method>(methods.size());
+ for (Method m : methods) {
+ boolean toBeAdded = true;
+
+ Iterator<Method> it = result.iterator();
+ while (it.hasNext()) {
+ Method other = it.next();
+ if (hasIdenticalParameters(m, other)) {
+ Class<?> mClass = m.getDeclaringClass();
+ Class<?> otherClass = other.getDeclaringClass();
+
+ if (mClass.isAssignableFrom(otherClass)) {
+ toBeAdded = false;
+ break;
+ } else if (otherClass.isAssignableFrom(mClass)) {
+ it.remove();
+ }
+ }
+ }
+
+ if (toBeAdded) result.add(m);
+ }
+
+ return result;
+ }
+
+ private static boolean hasIdenticalParameters(Method one, Method two) {
+ Class<?>[] oneTypes = one.getParameterTypes();
+ Class<?>[] twoTypes = two.getParameterTypes();
+
+ if (oneTypes.length != twoTypes.length) return false;
+
+ for (int i=0; i<oneTypes.length; i++) {
+ if (!oneTypes[i].equals(twoTypes[i])) return false;
+ }
+
+ return true;
+ }
+
+ private static List<Executable<Constructor<?>>> findConstructors(Type clazz, int size) {
+ List<Constructor<?>> constructors = new ArrayList<Constructor<?>>();
+ for (Constructor<?> constructor : ClassUtil.getClass(clazz).getConstructors()) {
+ if (constructor.getGenericParameterTypes().length != size) {
+ continue;
+ }
+ constructors.add(constructor);
+ }
+ List<Executable<Constructor<?>>> executables = new ArrayList<Executable<Constructor<?>>>();
+ for (Constructor<?> constructor : constructors) {
+ executables.add(new ConstructorExecutable(constructor));
+ }
+ return executables;
+ }
+
+ private static List<Executable<Method>> findMethods(Type clazz, String name, boolean instance, int size) {
+ List<Method> methods = new ArrayList<Method>();
+ for (Method method : ReflectionUtils.getPublicMethods(ClassUtil.getClass(clazz))) {
+ if (instance == Modifier.isStatic(method.getModifiers())) {
+ continue;
+ }
+ if (method.isBridge()) {
+ continue;
+ }
+ if (!method.getName().equals(name)) {
+ continue;
+ }
+ if (method.getGenericParameterTypes().length != size) {
+ continue;
+ }
+ methods.add(method);
+ }
+ if (!instance) {
+ methods = applyStaticHidingRules(methods);
+ }
+ List<Executable<Method>> executables = new ArrayList<Executable<Method>>();
+ for (Method method : methods) {
+ executables.add(new MethodExecutable(method));
+ }
+ return executables;
+ }
+
+ private static final long COST_ASSIGN = 1L;
+ private static final long COST_CAST = 100L;
+ private static final long COST_CONVERT = 10000L;
+
+ private static <E> List<Match<E>> findMatching(List<Executable<E>> executables, List<TypedObject> args, Converter converter, boolean reorder) {
+ Comparator<Match<E>> comparator = new Comparator<Match<E>>() {
+ @Override
+ public int compare(Match<E> o1, Match<E> o2) {
+ return o1.getScore() - o2.getScore();
+ }
+ };
+ List<Match<E>> matches = new ArrayList<Match<E>>();
+ for (Executable<E> e : executables) {
+ Match<E> match = match(e, args, converter);
+ if (match != null) {
+ matches.add(match);
+ }
+ }
+ Collections.sort(matches, comparator);
+ if (matches.isEmpty() && reorder) {
+ for (long p = 1, l = factorial(args.size()); p < l; p++) {
+ List<TypedObject> pargs = permutation(p, args);
+ for (Executable<E> e : executables) {
+ Match<E> match = match(e, pargs, converter);
+ if (match != null) {
+ matches.add(match);
+ }
+ }
+ }
+ Collections.sort(matches, comparator);
+ }
+ return matches;
+ }
+
+ private static <E> Match<E> match(Executable<E> executable, List<TypedObject> args, Converter converter) {
+ Map<TypeVariable<?>, Type> variables = new HashMap<TypeVariable<?>, Type>();
+ Type[] parameterTypes = executable.getGenericParameterTypes();
+ boolean allowCast = true;
+ for (int i = 0; i < parameterTypes.length; i++) {
+ TypedObject arg = args.get(i);
+ Type needed = parameterTypes[i];
+ if (GenericsUtil.containsTypeVariable(needed)
+ && ClassUtil.getClass(needed).isAssignableFrom(ClassUtil.getClass(arg.type))) {
+ try {
+ Type[] neededTypes = getParameters(needed);
+ Type[] actualTypes = getParameters(ClassUtil.getClass(needed), arg.type);
+ for (int j = 0; j < neededTypes.length; j++) {
+ if (neededTypes[j] instanceof TypeVariable) {
+ TypeVariable tv = (TypeVariable) neededTypes[j];
+ Type t = variables.get(tv);
+ t = mergeBounds(t, actualTypes[j]);
+ variables.put(tv, t);
+ }
+ }
+ } catch (IllegalArgumentException e) {
+ allowCast = false;
+ }
+ }
+ }
+
+ int score = 0;
+ List<TypedObject> converted = new ArrayList<TypedObject>();
+ for (int i = 0; i < parameterTypes.length; i++) {
+ TypedObject arg = args.get(i);
+ Type needed = parameterTypes[i];
+ long sc;
+ if (needed == arg.type) {
+ sc = COST_ASSIGN;
+ } else if (allowCast && ClassUtil.getClass(needed).isAssignableFrom(ClassUtil.getClass(arg.type))) {
+ sc = COST_CAST;
+ } else {
+ sc = COST_CONVERT;
+ }
+ try {
+ Type real = mapVariables(needed, variables);
+ converted.add(converter.convert(arg, real));
+ score += sc;
+ } catch (Exception e) {
+ return null;
+ }
+ }
+ return new Match<E>(executable.getMember(), converted, variables, score);
+ }
+
+ private static Type[] mapVariables(Type[] types, Map<TypeVariable<?>, Type> variables) {
+ Type[] resolved = new Type[types.length];
+ for (int i = 0; i < types.length; i++) {
+ resolved[i] = mapVariables(types[i], variables);
+ }
+ return resolved;
+ }
+
+ private static Type mapVariables(Type type, Map<TypeVariable<?>, Type> variables) {
+ if (type == null) {
+ return null;
+ } else if (type instanceof Class) {
+ return type;
+ } else if (type instanceof ParameterizedType) {
+ ParameterizedType pt = (ParameterizedType) type;
+ return new OwbParametrizedTypeImpl(
+ mapVariables(pt.getOwnerType(), variables),
+ mapVariables(pt.getRawType(), variables),
+ mapVariables(pt.getActualTypeArguments(), variables));
+ } else if (type instanceof TypeVariable) {
+ return variables.containsKey(type) ? variables.get(type) : type;
+ } else if (type instanceof WildcardType) {
+ WildcardType wt = (WildcardType) type;
+ return new OwbWildcardTypeImpl(
+ mapVariables(wt.getUpperBounds(), variables),
+ mapVariables(wt.getLowerBounds(), variables));
+ } else if (type instanceof GenericArrayType) {
+ GenericArrayType gat = (GenericArrayType) type;
+ return new OwbGenericArrayTypeImpl(mapVariables(gat.getGenericComponentType(), variables));
+ } else {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ private static Type mergeBounds(Type t1, Type t2) {
+ Set<Type> types = new HashSet<Type>();
+ TypeVariable vt = null;
+ if (t1 instanceof TypeVariable) {
+ Collections.addAll(types, ((TypeVariable) t1).getBounds());
+ vt = (TypeVariable) t1;
+ } else if (t1 != null) {
+ types.add(t1);
+ }
+ if (t2 instanceof TypeVariable) {
+ Collections.addAll(types, ((TypeVariable) t2).getBounds());
+ vt = (TypeVariable) t2;
+ } else if (t2 != null) {
+ types.add(t2);
+ }
+ List<Type> bounds = new ArrayList<Type>();
+ Class cl = null;
+ for (Type type : types) {
+ if (isClass(type)) {
+ cl = cl != null ? reduceClasses(cl, (Class) type) : (Class) type;
+ }
+ }
+ if (cl != null) {
+ bounds.add(cl);
+ }
+ List<Type> l = Collections.emptyList();
+ for (Type type : types) {
+ if (!isClass(type)) {
+ l = reduceTypes(l, Collections.singletonList(type));
+ }
+ }
+ bounds.addAll(l);
+ if (bounds.size() == 1) {
+ return bounds.get(0);
+ } else {
+ return OwbTypeVariableImpl.createTypeVariable(vt, bounds.toArray(new Type[bounds.size()]));
+ }
+ }
+
+ private static boolean isClass(Type t) {
+ Class c = ClassUtil.getClass(t);
+ return !c.isInterface() && !c.isEnum();
+ }
+
+ private static List<Type> reduceTypes(List<Type> l1, List<Type> l2) {
+ List<Type> types = new ArrayList<Type>();
+ for (Type t1 : l1) {
+ boolean discard = false;
+ for (Type t2 : l2) {
+ discard |= GenericsUtil.isAssignableFrom(false, false, t1, t2);
+ }
+ if (!discard) {
+ types.add(t1);
+ }
+ }
+ for (Type t2 : l2) {
+ boolean discard = false;
+ for (Type t1 : l1) {
+ discard |= GenericsUtil.isAssignableFrom(false, false, t1, t2);
+ }
+ if (!discard) {
+ types.add(t2);
+ }
+ }
+ return types;
+ }
+
+ private static Class reduceClasses(Class<?> c1, Class<?> c2) {
+ if (c1.isAssignableFrom(c2)) {
+ return c1;
+ } else if (c2.isAssignableFrom(c1)) {
+ return c2;
+ } else {
+ throw new IllegalArgumentException("Illegal bounds: " + c1 + ", " + c2);
+ }
+ }
+
+ private static Type[] getParameters(Class<?> neededClass, Type type) {
+ return GenericsUtil.resolveTypes(getParameters(neededClass), type);
+ }
+
+ private static long factorial(int n) {
+ if (n > 20 || n < 0) throw new IllegalArgumentException(n + " is out of range");
+ long l = 1L;
+ for (int i = 2; i <= n; i++) {
+ l *= i;
+ }
+ return l;
+ }
+
+ private static <T> List<T> permutation(long no, List<T> items) {
+ return permutationHelper(no, new LinkedList<T>(items), new ArrayList<T>());
+ }
+
+ private static <T> List<T> permutationHelper(long no, LinkedList<T> in, List<T> out) {
+ if (in.isEmpty()) return out;
+ long subFactorial = factorial(in.size() - 1);
+ out.add(in.remove((int) (no / subFactorial)));
+ return permutationHelper((int) (no % subFactorial), in, out);
+ }
+
+ private static Type[] getParameters(Type type) {
+ if (type instanceof Class) {
+ Class clazz = (Class) type;
+ if (clazz.isArray()) {
+ return clazz.getComponentType().getTypeParameters();
+ } else {
+ return clazz.getTypeParameters();
+ }
+ }
+ if (type instanceof ParameterizedType) {
+ return ((ParameterizedType) type).getActualTypeArguments();
+ }
+ throw new RuntimeException("Unknown type " + 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=1822706&r1=1822705&r2=1822706&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 Tue Jan 30 22:05:17 2018
@@ -18,7 +18,6 @@
*/
package org.apache.aries.blueprint;
-import java.lang.reflect.Constructor;
import java.math.BigInteger;
import java.net.URI;
import java.util.ArrayList;
@@ -37,9 +36,7 @@ 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;
@@ -55,10 +52,6 @@ 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;
@@ -468,7 +461,41 @@ public class WiringTest extends Abstract
assertTrue(obj instanceof Primavera);
assertEquals("stringToo", ((Primavera) obj).prop);
}
-
+
+ public void testMixedGenericsTyped() throws Exception {
+ ComponentDefinitionRegistryImpl registry = parse("/test-generics-mix.xml");
+ Repository repository = new TestBlueprintContainer(registry).getRepository();
+ try {
+ repository.create("typedTracker");
+ fail("Should have thrown an exception");
+ } catch (ComponentDefinitionException e) {
+ // expected
+ }
+ }
+
+ public void testMixedGenericsTypedGeneric() throws Exception {
+ ComponentDefinitionRegistryImpl registry = parse("/test-generics-mix.xml");
+ Repository repository = new TestBlueprintContainer(registry).getRepository();
+ repository.create("typedGenericTracker");
+ }
+
+ public void testMixedGenericsTypedClass() throws Exception {
+ ComponentDefinitionRegistryImpl registry = parse("/test-generics-mix.xml");
+ Repository repository = new TestBlueprintContainer(registry).getRepository();
+ try {
+ repository.create("typedClassTracker");
+ fail("Should have thrown an exception");
+ } catch (ComponentDefinitionException e) {
+ // expected
+ }
+ }
+
+ public void testMixedGenericsTypedGenericClass() throws Exception {
+ ComponentDefinitionRegistryImpl registry = parse("/test-generics-mix.xml");
+ Repository repository = new TestBlueprintContainer(registry).getRepository();
+ repository.create("typedClassGenericTracker");
+ }
+
public void testCircular() throws Exception {
BlueprintRepository repository = createBlueprintContainer().getRepository();
Modified: aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/BeanRecipeTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/BeanRecipeTest.java?rev=1822706&r1=1822705&r2=1822706&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/BeanRecipeTest.java (original)
+++ aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/BeanRecipeTest.java Tue Jan 30 22:05:17 2018
@@ -27,6 +27,7 @@ import java.util.Set;
import org.apache.aries.blueprint.di.ExecutionContext;
import org.apache.aries.blueprint.di.PassThroughRecipe;
+import org.apache.aries.blueprint.utils.generics.TypeInference;
import org.junit.Test;
import org.osgi.service.blueprint.container.ComponentDefinitionException;
@@ -300,7 +301,7 @@ public class BeanRecipeTest {
private Set<Method> applyStaticHidingRules(Collection<Method> methods) {
try {
- Method m = BeanRecipe.class.getDeclaredMethod("applyStaticHidingRules", Collection.class);
+ Method m = TypeInference.class.getDeclaredMethod("applyStaticHidingRules", Collection.class);
m.setAccessible(true);
return new HashSet<Method>((List<Method>) m.invoke(null, methods));
} catch (Exception e) {
Added: aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/TypeInferenceTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/TypeInferenceTest.java?rev=1822706&view=auto
==============================================================================
--- aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/TypeInferenceTest.java (added)
+++ aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/TypeInferenceTest.java Tue Jan 30 22:05:17 2018
@@ -0,0 +1,80 @@
+/*
+ * 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.container;
+
+import org.apache.aries.blueprint.TestBlueprintContainer;
+import org.apache.aries.blueprint.pojos.DummyServiceTrackerCustomizer;
+import org.apache.aries.blueprint.pojos.PojoA;
+import org.apache.aries.blueprint.utils.generics.OwbParametrizedTypeImpl;
+import org.apache.aries.blueprint.utils.generics.TypeInference;
+import org.junit.Test;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.blueprint.container.Converter;
+import org.osgi.util.tracker.ServiceTracker;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+
+import static org.junit.Assert.assertNotNull;
+
+public class TypeInferenceTest {
+
+ private final Converter converter;
+
+ public TypeInferenceTest() throws Exception {
+ converter = new AggregateConverter(new TestBlueprintContainer(null));
+ }
+
+ @Test
+ public void testSimple() {
+ TypeInference.Match<Constructor<?>> match = TypeInference.findMatchingConstructors(
+ ServiceTracker.class,
+ Arrays.asList(
+ new TypeInference.TypedObject(BundleContext.class, null),
+ new TypeInference.TypedObject(new OwbParametrizedTypeImpl(null, Class.class, PojoA.class), PojoA.class),
+ new TypeInference.TypedObject(DummyServiceTrackerCustomizer.class, null)),
+ new TIConverter(),
+ false)
+ .get(0);
+ assertNotNull(match);
+ }
+
+ @Test
+ public void testReorder() {
+ TypeInference.Match<Constructor<?>> match = TypeInference.findMatchingConstructors(
+ ServiceTracker.class,
+ Arrays.asList(
+ new TypeInference.TypedObject(new OwbParametrizedTypeImpl(null, Class.class, PojoA.class), PojoA.class),
+ new TypeInference.TypedObject(BundleContext.class, null),
+ new TypeInference.TypedObject(DummyServiceTrackerCustomizer.class, null)),
+ new TIConverter(),
+ true)
+ .get(0);
+ assertNotNull(match);
+ }
+
+ class TIConverter implements TypeInference.Converter {
+ public TypeInference.TypedObject convert(TypeInference.TypedObject from, Type to) throws Exception {
+ Object arg = from.getValue();
+ arg = converter.convert(arg, new GenericType(to));
+ return new TypeInference.TypedObject(to, arg);
+ }
+ }
+}
Added: aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/pojos/DummyServiceTrackerCustomizer.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/pojos/DummyServiceTrackerCustomizer.java?rev=1822706&view=auto
==============================================================================
--- aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/pojos/DummyServiceTrackerCustomizer.java (added)
+++ aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/pojos/DummyServiceTrackerCustomizer.java Tue Jan 30 22:05:17 2018
@@ -0,0 +1,39 @@
+/*
+ * 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 org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+
+public class DummyServiceTrackerCustomizer implements ServiceTrackerCustomizer<PojoA, PojoB> {
+ @Override
+ public PojoB addingService(ServiceReference<PojoA> reference) {
+ return null;
+ }
+
+ @Override
+ public void modifiedService(ServiceReference<PojoA> reference, PojoB service) {
+
+ }
+
+ @Override
+ public void removedService(ServiceReference<PojoA> reference, PojoB service) {
+
+ }
+}
Added: aries/trunk/blueprint/blueprint-core/src/test/resources/test-generics-mix.xml
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/test/resources/test-generics-mix.xml?rev=1822706&view=auto
==============================================================================
--- aries/trunk/blueprint/blueprint-core/src/test/resources/test-generics-mix.xml (added)
+++ aries/trunk/blueprint/blueprint-core/src/test/resources/test-generics-mix.xml Tue Jan 30 22:05:17 2018
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ default-availability="mandatory" >
+
+ <bean id="tracker" class="org.osgi.util.tracker.ServiceTracker">
+ <argument ref="blueprintBundleContext" />
+ <argument value="org.apache.aries.blueprint.pojos.PojoA" />
+ <argument>
+ <bean class="org.apache.aries.blueprint.pojos.DummyServiceTrackerCustomizer" />
+ </argument>
+ </bean>
+
+ <bean id="typedTracker" class="org.osgi.util.tracker.ServiceTracker">
+ <argument type="org.osgi.framework.BundleContext" ref="blueprintBundleContext" />
+ <argument type="java.lang.String" value="org.apache.aries.blueprint.pojos.PojoA" />
+ <argument type="org.osgi.util.tracker.ServiceTrackerCustomizer">
+ <bean class="org.apache.aries.blueprint.pojos.DummyServiceTrackerCustomizer" />
+ </argument>
+ </bean>
+
+ <bean id="typedGenericTracker" class="org.osgi.util.tracker.ServiceTracker">
+ <argument type="org.osgi.framework.BundleContext" ref="blueprintBundleContext" />
+ <argument type="java.lang.String" value="org.apache.aries.blueprint.pojos.PojoA" />
+ <argument type="org.osgi.util.tracker.ServiceTrackerCustomizer<org.apache.aries.blueprint.pojos.PojoA,org.apache.aries.blueprint.pojos.PojoB>">
+ <bean class="org.apache.aries.blueprint.pojos.DummyServiceTrackerCustomizer" />
+ </argument>
+ </bean>
+
+ <bean id="typedClassTracker" class="org.osgi.util.tracker.ServiceTracker">
+ <argument type="org.osgi.framework.BundleContext" ref="blueprintBundleContext" />
+ <argument type="java.lang.Class">
+ <bean class="java.lang.Class" factory-method="forName">
+ <argument value="org.apache.aries.blueprint.pojos.PojoA" />
+ </bean>
+ </argument>
+ <argument type="org.osgi.util.tracker.ServiceTrackerCustomizer">
+ <bean class="org.apache.aries.blueprint.pojos.DummyServiceTrackerCustomizer" />
+ </argument>
+ </bean>
+
+ <bean id="typedClassGenericTracker" class="org.osgi.util.tracker.ServiceTracker">
+ <argument type="org.osgi.framework.BundleContext" ref="blueprintBundleContext" />
+ <argument type="java.lang.Class<org.apache.aries.blueprint.pojos.PojoA>">
+ <bean class="java.lang.Class" factory-method="forName">
+ <argument value="org.apache.aries.blueprint.pojos.PojoA" />
+ </bean>
+ </argument>
+ <argument type="org.osgi.util.tracker.ServiceTrackerCustomizer<org.apache.aries.blueprint.pojos.PojoA,org.apache.aries.blueprint.pojos.PojoB>">
+ <bean class="org.apache.aries.blueprint.pojos.DummyServiceTrackerCustomizer" />
+ </argument>
+ </bean>
+
+</blueprint>