You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by ma...@apache.org on 2010/06/05 11:39:47 UTC

svn commit: r951687 - in /incubator/aries/trunk/blueprint/blueprint-core/src: main/java/org/apache/aries/blueprint/container/BeanRecipe.java test/java/org/apache/aries/blueprint/container/BeanRecipeTest.java

Author: mahrwald
Date: Sat Jun  5 09:39:46 2010
New Revision: 951687

URL: http://svn.apache.org/viewvc?rev=951687&view=rev
Log:
ARIES-325: Add cross-JVM static factory method disambiguation.

Added:
    incubator/aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/BeanRecipeTest.java
Modified:
    incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BeanRecipe.java

Modified: incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BeanRecipe.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BeanRecipe.java?rev=951687&r1=951686&r2=951687&view=diff
==============================================================================
--- incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BeanRecipe.java (original)
+++ incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BeanRecipe.java Sat Jun  5 09:39:46 2010
@@ -26,6 +26,7 @@ import java.lang.reflect.Modifier;
 import java.lang.reflect.Type;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
@@ -287,6 +288,13 @@ public class BeanRecipe extends Abstract
                 it.remove();
             }
         }
+        
+        // on some JVMs (J9) hidden static methods are returned by Class.getMethods so we need to weed them out
+        // to reduce ambiguity
+        if (!instance) {
+        	methods = applyStaticHidingRules(methods);
+        }
+        
         // Find a direct match with assignment
         if (matches.size() != 1) {
             Map<Method, List<Object>> nmatches = new HashMap<Method, List<Object>>();
@@ -374,8 +382,49 @@ public class BeanRecipe extends Abstract
                 matches = nmatches;
             }
         }
+        
         return matches;
     }
+    
+    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();
+    		inner: 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 inner;
+    				} 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 Map<Constructor, List<Object>> findMatchingConstructors(Class type, List<Object> args, List<ReifiedType> types) {
         Map<Constructor, List<Object>> matches = new HashMap<Constructor, List<Object>>();

Added: incubator/aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/BeanRecipeTest.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/BeanRecipeTest.java?rev=951687&view=auto
==============================================================================
--- incubator/aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/BeanRecipeTest.java (added)
+++ incubator/aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/BeanRecipeTest.java Sat Jun  5 09:39:46 2010
@@ -0,0 +1,135 @@
+/*
+ * 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 java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+public class BeanRecipeTest {
+	static class Base {
+		public static Object getObject() { return null; }
+		public static Object getOne(Object o) { return null; }
+
+		public static Object getMany(Object o, String n, String n2) { return null; }
+	}
+	
+	static class Middle extends Base {
+		public static Number getObject() { return null; }
+		public static Number getOne(Number n) { return null; }
+		public static Number getOne(Object o) { return null; }
+		
+		public static Object getMany(Object o, String n, Number i) { return null; }
+		public static Object getBasic(int n) { return 0; }
+	}
+	
+	static class Top extends Middle {
+		public static Integer getObject() { return null; }
+		public static Integer getOne(Integer n) { return null; }
+		
+		public static Object getMany(Object o, String n, Number i) { return null; }
+		public static Object getBasic(int n) { return 0; }
+	}
+	
+	static class Unrelated {
+		public static String getObject() { return null; }
+		public static Object getBasic(int n) { return 1; }
+	}
+	
+	@Test
+	public void parameterLessHiding() throws Exception {
+		Set<Method> methods = new HashSet<Method>(
+				Arrays.asList(
+						Base.class.getMethod("getObject"),
+						Middle.class.getMethod("getObject"),
+						Top.class.getMethod("getObject"),
+						Unrelated.class.getMethod("getObject")
+				));
+		
+		methods = applyStaticHidingRules(methods);
+
+		assertEquals(2, methods.size());
+		assertTrue(methods.contains(Top.class.getMethod("getObject")));
+		assertTrue(methods.contains(Unrelated.class.getMethod("getObject")));
+		assertFalse(methods.contains(Middle.class.getMethod("getObject")));
+	}
+	
+	@Test
+	public void parameterDistinction() throws Exception {
+		Set<Method> methods = new HashSet<Method>(
+				Arrays.asList(
+						Base.class.getMethod("getOne", Object.class),
+						Middle.class.getMethod("getOne", Number.class),
+						Middle.class.getMethod("getOne", Object.class),
+						Top.class.getMethod("getOne", Integer.class)
+				));
+		
+		methods = applyStaticHidingRules(methods);
+		
+		assertEquals(3, methods.size());
+		assertFalse(methods.contains(Base.class.getMethod("getOne", Object.class)));
+	}
+	
+	@Test
+	public void multiParameterTest() throws Exception {
+		Set<Method> methods = new HashSet<Method>(
+				Arrays.asList(
+						Base.class.getMethod("getMany", Object.class, String.class, String.class),
+						Middle.class.getMethod("getMany", Object.class, String.class, Number.class),
+						Top.class.getMethod("getMany", Object.class, String.class, Number.class)
+				));
+		
+		methods = applyStaticHidingRules(methods);
+		
+		assertEquals(2, methods.size());
+		assertFalse(methods.contains(Middle.class.getMethod("getMany", Object.class, String.class, Number.class)));
+		
+	}
+	
+	@Test
+	public void baseTypeHiding() throws Exception {
+		Set<Method> methods = new HashSet<Method>(
+				Arrays.asList(
+						Middle.class.getMethod("getBasic", int.class),
+						Top.class.getMethod("getBasic", int.class),
+						Unrelated.class.getMethod("getBasic", int.class)
+				));
+		
+		methods = applyStaticHidingRules(methods);
+		
+		assertEquals(2, methods.size());
+		assertFalse(methods.contains(Middle.class.getMethod("getBasic", int.class)));
+	}
+	
+	private Set<Method> applyStaticHidingRules(Collection<Method> methods) {
+		try {
+			Method m = BeanRecipe.class.getDeclaredMethod("applyStaticHidingRules", Collection.class);
+			m.setAccessible(true);
+			return new HashSet<Method>((List<Method>) m.invoke(null, methods));
+		} catch (Exception e) { 
+			throw new RuntimeException(e);
+		}
+	}
+}