Additional fixes for https://bugs.eclipse.org/bugs/show_bug.cgi?id=392500
Recursive Generics can me mutually recursive, Multi-bounded and wildcard-scoped.

Conflicts:
	core/src/test/java/org/eclipse/gemini/blueprint/blueprint/container/TypeFactoryTest.java

Fix compilation errors
diff --git a/core/src/main/java/org/eclipse/gemini/blueprint/blueprint/container/TypeFactory.java b/core/src/main/java/org/eclipse/gemini/blueprint/blueprint/container/TypeFactory.java
index aded1e0..336201a 100644
--- a/core/src/main/java/org/eclipse/gemini/blueprint/blueprint/container/TypeFactory.java
+++ b/core/src/main/java/org/eclipse/gemini/blueprint/blueprint/container/TypeFactory.java
@@ -20,6 +20,7 @@
 import java.lang.reflect.TypeVariable;
 import java.lang.reflect.WildcardType;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
@@ -104,13 +105,13 @@
         TypeVariable[] tvs = type.getType().getTypeParameters();
         arguments = new ArrayList<ReifiedType>(tvs.length);
         for (@SuppressWarnings("rawtypes") TypeVariable tv : tvs) {
-            ReifiedType rType = getReifiedType(tv);
+            ReifiedType rType = getReifiedType(tv, null);
             arguments.add(rType);
         }
         return arguments;
 	}
 
-	private static ReifiedType getReifiedType(Type targetType) {
+	private static ReifiedType getReifiedType(Type targetType, Collection<Type> variableTypes) {
 		if (targetType instanceof Class) {
 			if (Object.class.equals(targetType)) {
 				return OBJECT;
@@ -119,7 +120,7 @@
 		}
 		if (targetType instanceof ParameterizedType) {
 			Type ata = ((ParameterizedType) targetType).getActualTypeArguments()[0];
-			return getReifiedType(ata);
+			return getReifiedType(ata, variableTypes);
 		}
 		if (targetType instanceof WildcardType) {
 			WildcardType wt = (WildcardType) targetType;
@@ -127,29 +128,37 @@
 			if (ObjectUtils.isEmpty(lowerBounds)) {
 				// there's always an upper bound (Object)
 				Type upperBound = wt.getUpperBounds()[0];
-				return getReifiedType(upperBound);
+				return getReifiedType(upperBound, variableTypes);
 			}
 
-			return getReifiedType(lowerBounds[0]);
+			return getReifiedType(lowerBounds[0], variableTypes);
 		}
 
 		if (targetType instanceof TypeVariable) {
 			TypeVariable<?> typeVariable = (TypeVariable<?>) targetType;
+			if (variableTypes == null) {
+				variableTypes = new ArrayList<Type>(2);
+			} else if (variableTypes.contains(targetType)) {
+				//Looped around on itself via a recursive Generics definition
+				return OBJECT;
+			}
+			variableTypes.add(targetType);
 			Type[] bounds = typeVariable.getBounds();
-			Type boundZero = bounds[0];
-			if (bounds.length == 1 && boundZero instanceof ParameterizedType) {
-				Type ata = ((ParameterizedType) boundZero).getActualTypeArguments()[0];
-				if (targetType.equals(ata)) {
-					//recursive declaration like <T extends Comparable<T>>
-					return OBJECT;
+			for (Type bound : bounds) {
+				if (bound instanceof ParameterizedType) {
+					Type ata = ((ParameterizedType) bound).getActualTypeArguments()[0];
+					if (ata instanceof TypeVariable) {
+						variableTypes.add(ata);
+					}
+					return getReifiedType(bound, variableTypes);
 				}
 			}
 
-			return getReifiedType(boundZero);
+			return getReifiedType(bounds[0], variableTypes);
 		}
 
 		if (targetType instanceof GenericArrayType) {
-			return getReifiedType(((GenericArrayType) targetType).getGenericComponentType());
+			return getReifiedType(((GenericArrayType) targetType).getGenericComponentType(), variableTypes);
 		}
 
 		throw new IllegalArgumentException("Unknown type " + targetType.getClass());
diff --git a/core/src/test/java/org/eclipse/gemini/blueprint/blueprint/container/TypeFactoryTest.java b/core/src/test/java/org/eclipse/gemini/blueprint/blueprint/container/TypeFactoryTest.java
index b762de0..e56745d 100644
--- a/core/src/test/java/org/eclipse/gemini/blueprint/blueprint/container/TypeFactoryTest.java
+++ b/core/src/test/java/org/eclipse/gemini/blueprint/blueprint/container/TypeFactoryTest.java
@@ -54,8 +54,8 @@
 		public void typedList(LinkedList<Point> arg) {
 		}
 
-        public void array(Integer[] arg) {
-        }
+		public void array(Integer[] arg) {
+		}
 
 		public void extendsList(LinkedList<? extends Shape> arg) {
 		}
@@ -94,23 +94,28 @@
 	private static class RecursiveGenericType<T extends Comparable<T>> {
 	}
 
-	private static class SingleAndRecursiveGenericType<S extends String, T extends Comparable<T>> {
+	private static class SingleAndRecursiveGenericType<S extends String, T extends Comparable<S>> {
 	}
 
 	private static class MultipleRecursiveGenericType<T extends Comparable<T>, U extends T> {
 	}
-	
+
 	private static class MutuallyRecursiveGenericType<T extends Comparable<U>, U extends Comparable<T>> {
-	    // Must T always equal U?
+		// Must T always equal U?
 	}
-	
+
 	private static class ComplexRecursiveGenericType<T extends Comparable<? super T>> {
 	}
-	
+
 	private static class MultiBoundedRecursiveGenericType<T extends Comparable<T> & Cloneable> {
-	    // Cloneable could be replaced by any interface
+		// Cloneable could be replaced by any interface
 	}
-	
+
+	private static interface Ice {}
+	private static interface Juice {}
+	private static class A<T extends Ice & Juice> {}
+	private static class B<T extends Juice & Ice> {}
+
 	@Test
 	public void testJdk4Classes() throws Exception {
 		ReifiedType tp = getReifiedTypeFor("rawList");
@@ -118,29 +123,29 @@
 		assertEquals(List.class, tp.getRawClass());
 	}
 
-    @Test
+	@Test
 	public void testPrimitive() throws Exception {
 		ReifiedType tp = getReifiedTypeFor("primitive");
 		assertEquals(0, tp.size());
 		assertEquals(Integer.class, tp.getRawClass());
 	}
 
-    @Test
+	@Test
 	public void testArray() throws Exception {
 		ReifiedType tp = getReifiedTypeFor("array");
 		assertEquals(1, tp.size());
 		assertEquals(Integer[].class, tp.getRawClass());
-        assertEquals(Integer.class, tp.getActualTypeArgument(0).getRawClass());
+		assertEquals(Integer.class, tp.getActualTypeArgument(0).getRawClass());
 	}
 
-    @Test
+	@Test
 	public void testInteger() throws Exception {
 		ReifiedType tp = getReifiedTypeFor("integer");
 		assertEquals(0, tp.size());
 		assertEquals(Integer.class, tp.getRawClass());
 	}
 
-    @Test
+	@Test
 	public void testTypedObjectList() throws Exception {
 		ReifiedType tp = getReifiedTypeFor("typedList");
 		assertEquals(1, tp.size());
@@ -148,7 +153,7 @@
 		assertEquals(Point.class, tp.getActualTypeArgument(0).getRawClass());
 	}
 
-    @Test
+	@Test
 	public void testExtendsList() throws Exception {
 		ReifiedType tp = getReifiedTypeFor("extendsList");
 		assertEquals(1, tp.size());
@@ -156,7 +161,7 @@
 		assertEquals(Shape.class, tp.getActualTypeArgument(0).getRawClass());
 	}
 
-    @Test
+	@Test
 	public void testSuperList() throws Exception {
 		ReifiedType tp = getReifiedTypeFor("superList");
 		assertEquals(1, tp.size());
@@ -164,7 +169,7 @@
 		assertEquals(Shape.class, tp.getActualTypeArgument(0).getRawClass());
 	}
 
-    @Test
+	@Test
 	public void testTypedMap() throws Exception {
 		ReifiedType tp = getReifiedTypeFor("typedMap");
 		assertEquals(2, tp.size());
@@ -173,7 +178,7 @@
 		assertEquals(Double.class, tp.getActualTypeArgument(1).getRawClass());
 	}
 
-    @Test
+	@Test
 	public void testPointMap() throws Exception {
 		ReifiedType tp = getReifiedTypeFor("pointMap");
 		assertEquals(2, tp.size());
@@ -182,59 +187,59 @@
 		assertEquals(Point.class, tp.getActualTypeArgument(1).getRawClass());
 	}
 
-    // Since spring 3.1 the TypeDescriptor no longer contains any reference to the MethodParameter
-    // class, we we are unable to get the ParameterizedType of a method parameter.
-    // So all actual type arguments just become Object.class.
+	// Since spring 3.1 the TypeDescriptor no longer contains any reference to the MethodParameter
+	// class, we we are unable to get the ParameterizedType of a method parameter.
+	// So all actual type arguments just become Object.class.
 	@Test
-    @Ignore
-    public void testTypedReference() throws Exception {
+	@Ignore
+	public void testTypedReference() throws Exception {
 		ReifiedType tp = getReifiedTypeFor("typedReference");
 		assertEquals(AtomicReference.class, tp.getRawClass());
-        assertEquals(1, tp.size());
-        assertEquals(Boolean.class, tp.getActualTypeArgument(0).getRawClass());
+		assertEquals(1, tp.size());
+		assertEquals(Boolean.class, tp.getActualTypeArgument(0).getRawClass());
 	}
 
-    @Test
+	@Test
 	public void testObjectTypedReference() throws Exception {
 		ReifiedType tp = getReifiedTypeFor("objectTypedReference");
 		assertEquals(AtomicReference.class, tp.getRawClass());
-        assertEquals(1, tp.size());
-        assertEquals(Object.class, tp.getActualTypeArgument(0).getRawClass());
+		assertEquals(1, tp.size());
+		assertEquals(Object.class, tp.getActualTypeArgument(0).getRawClass());
 	}
 
-    @Test
+	@Test
 	public void testWildcardReference() throws Exception {
 		ReifiedType tp = getReifiedTypeFor("wildcardReference");
 		assertEquals(AtomicReference.class, tp.getRawClass());
-        assertEquals(1, tp.size());
-        assertEquals(Object.class, tp.getActualTypeArgument(0).getRawClass());
+		assertEquals(1, tp.size());
+		assertEquals(Object.class, tp.getActualTypeArgument(0).getRawClass());
 	}
 
-    // Since spring 3.1 the TypeDescriptor no longer contains any reference to the MethodParameter
-    // class, we we are unable to get the ParameterizedType of a method parameter.
-    // So all actual type arguments just become Object.class.
-    @Test
-    @Ignore
+	// Since spring 3.1 the TypeDescriptor no longer contains any reference to the MethodParameter
+	// class, we we are unable to get the ParameterizedType of a method parameter.
+	// So all actual type arguments just become Object.class.
+	@Test
+	@Ignore
 	public void testSuperReference() throws Exception {
 		ReifiedType tp = getReifiedTypeFor("superTypedReference");
 		assertEquals(AtomicReference.class, tp.getRawClass());
-        assertEquals(1, tp.size());
-        assertEquals(Properties.class, tp.getActualTypeArgument(0).getRawClass());
+		assertEquals(1, tp.size());
+		assertEquals(Properties.class, tp.getActualTypeArgument(0).getRawClass());
 	}
 
-    // Since spring 3.1 the TypeDescriptor no longer contains any reference to the MethodParameter
-    // class, we we are unable to get the ParameterizedType of a method parameter.
-    // So all actual type arguments just come Object.class.
-    @Test
-    @Ignore
+	// Since spring 3.1 the TypeDescriptor no longer contains any reference to the MethodParameter
+	// class, we we are unable to get the ParameterizedType of a method parameter.
+	// So all actual type arguments just come Object.class.
+	@Test
+	@Ignore
 	public void testExtendsReference() throws Exception {
 		ReifiedType tp = getReifiedTypeFor("extendsTypedReference");
 		assertEquals(AtomicReference.class, tp.getRawClass());
-        assertEquals(1, tp.size());
-        assertEquals(Properties.class, tp.getActualTypeArgument(0).getRawClass());
+		assertEquals(1, tp.size());
+		assertEquals(Properties.class, tp.getActualTypeArgument(0).getRawClass());
 	}
 
-    @Test
+	@Test
 	public void testTypeVariable() throws Exception {
 		ReifiedType tp = getReifiedTypeFor("typeVariable");
 		assertEquals(1, tp.size());
@@ -242,7 +247,7 @@
 		assertEquals(Object.class, tp.getActualTypeArgument(0).getRawClass());
 	}
 
-    @Test
+	@Test
 	public void testCustomDictionary() throws Exception {
 		ReifiedType tp = getReifiedTypeFor("customDictionary");
 		assertEquals(2, tp.size());
@@ -251,41 +256,50 @@
 		assertEquals(Object.class, tp.getActualTypeArgument(1).getRawClass());
 	}
 
-    @Test
+	@Test
 	public void testUnknownType() throws Exception {
 		ReifiedType type = TypeFactory.getType(TypeDescriptor.forObject(null));
 		assertEquals(Object.class, type.getRawClass());
 	}
 
-    @Test
+	@Test
 	public void testRecursiveGenericType() throws Exception {
 		assertNotNull(TypeFactory.getType(TypeDescriptor.valueOf(RecursiveGenericType.class)));
 	}
 
-    @Test
-    public void testSingleAndRecursiveGenericType() throws Exception {
-        assertNotNull(TypeFactory.getType(TypeDescriptor.valueOf(SingleAndRecursiveGenericType.class)));
-    }
+	@Test
+	public void testSingleAndRecursiveGenericType() throws Exception {
+		assertNotNull(TypeFactory.getType(TypeDescriptor.valueOf(SingleAndRecursiveGenericType.class)));
+	}
 
-    @Test
-    public void testMultipleRecursiveGenericType() throws Exception {
-        assertNotNull(TypeFactory.getType(TypeDescriptor.valueOf(MultipleRecursiveGenericType.class)));
-    }
+	@Test
+	public void testMultipleRecursiveGenericType() throws Exception {
+		assertNotNull(TypeFactory.getType(TypeDescriptor.valueOf(MultipleRecursiveGenericType.class)));
+	}
 
-    @Test
-    public void testMutuallyRecursiveGenericType() throws Exception {
-        assertNotNull(TypeFactory.getType(TypeDescriptor.valueOf(MutuallyRecursiveGenericType.class)));
-    }
+	@Test
+	public void testMutuallyRecursiveGenericType() throws Exception {
+		assertNotNull(TypeFactory.getType(TypeDescriptor.valueOf(MutuallyRecursiveGenericType.class)));
+	}
 
-    @Test
-    public void testComplexRecursiveGenericType() throws Exception {
-        assertNotNull(TypeFactory.getType(TypeDescriptor.valueOf(ComplexRecursiveGenericType.class)));
-    }
+	@Test
+	public void testComplexRecursiveGenericType() throws Exception {
+		assertNotNull(TypeFactory.getType(TypeDescriptor.valueOf(ComplexRecursiveGenericType.class)));
+	}
 
-    @Test
-    public void testMultiBoundedRecursiveGenericType() throws Exception {
-        assertNotNull(TypeFactory.getType(TypeDescriptor.valueOf(MultiBoundedRecursiveGenericType.class)));
-    }
+	@Test
+	public void testMultiBoundedRecursiveGenericType() throws Exception {
+		assertNotNull(TypeFactory.getType(TypeDescriptor.valueOf(MultiBoundedRecursiveGenericType.class)));
+	}
+
+	@Test
+	public void testMultiBoundedGenericType() throws Exception {
+		ReifiedType reifiedA = TypeFactory.getType(TypeDescriptor.valueOf(A.class));
+		assertNotNull(reifiedA);
+		ReifiedType reifiedB = TypeFactory.getType(TypeDescriptor.valueOf(B.class));
+		assertNotNull(reifiedB);
+	}
+
 
 	private ReifiedType getReifiedTypeFor(String methodName) {
 		Method mt = BeanUtils.findDeclaredMethodWithMinimalParameters(TestSet.class, methodName);