You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2005/10/03 13:53:54 UTC

svn commit: r293319 - /jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/enhance/EnhancedClassValidatorImpl.java

Author: hlship
Date: Mon Oct  3 04:53:51 2005
New Revision: 293319

URL: http://svn.apache.org/viewcvs?rev=293319&view=rev
Log:
TAPESTRY-344: Unimplemented abstract method check broken

Modified:
    jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/enhance/EnhancedClassValidatorImpl.java

Modified: jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/enhance/EnhancedClassValidatorImpl.java
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/enhance/EnhancedClassValidatorImpl.java?rev=293319&r1=293318&r2=293319&view=diff
==============================================================================
--- jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/enhance/EnhancedClassValidatorImpl.java (original)
+++ jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/enhance/EnhancedClassValidatorImpl.java Mon Oct  3 04:53:51 2005
@@ -16,10 +16,10 @@
 
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.HashMap;
 import java.util.HashSet;
-import java.util.List;
+import java.util.Iterator;
+import java.util.Map;
 import java.util.Set;
 
 import org.apache.hivemind.ErrorLog;
@@ -40,26 +40,49 @@
 
     public void validate(Class baseClass, Class enhancedClass, IComponentSpecification specification)
     {
+        // Set of MethodSignatures for methods that have a non-abstract implementation
+        // The Set is built working from the deepest subclass up to (and including) java.lang.Object
+
         Set implementedMethods = new HashSet();
-        List interfaceQueue = new ArrayList();
+        // Key is MethodSignature, value is Method
+        // Tracks which methods come from interfaces
+        Map interfaceMethods = new HashMap();
+
         Location location = specification.getLocation();
 
         Class current = enhancedClass;
 
         while (true)
         {
+            addInterfaceMethods(current, interfaceMethods);
+
+            // Inside Eclipse, for abstract classes, getDeclaredMethods() does NOT report methods
+            // inherited from interfaces. For Sun JDK and abstract classes, getDeclaredMethods()
+            // DOES report interface methods
+            // (as if they were declared by the class itself). This code is needlessly complex so
+            // that the checks work in both
+            // situations. Basically, I think Eclipse is right and Sun JDK is wrong and we're using
+            // the interfaceMethods map as a filter to ignore methods that Sun JDK is attributing
+            // to the class.
+
             Method[] methods = current.getDeclaredMethods();
 
             for (int i = 0; i < methods.length; i++)
             {
                 Method m = methods[i];
 
-                boolean isAbstract = Modifier.isAbstract(m.getModifiers());
-
                 MethodSignature s = new MethodSignature(m);
 
+                boolean isAbstract = Modifier.isAbstract(m.getModifiers());
+
                 if (isAbstract)
                 {
+                    if (interfaceMethods.containsKey(s))
+                        continue;
+
+                    // If a superclass defines an abstract method that a subclass implements, then
+                    // all's OK.
+
                     if (implementedMethods.contains(s))
                         continue;
 
@@ -73,51 +96,56 @@
                 implementedMethods.add(s);
             }
 
-            interfaceQueue.addAll(Arrays.asList(current.getInterfaces()));
-
-            // Did an earlier JDK include methods from interfaces in
-            // getDeclaredMethods()? The old code here seemed to indicate
-            // that was the case, but it certainly is no longer, that's why
-            // we add all the interfaces to a queue to check after the rest.
-
             current = current.getSuperclass();
 
-            // We need to run straight to the top, to find all the implemented methods.
+            // No need to check Object.class; it is concrete and doesn't implement any interfaces,
+            // or provide any methods
+            // that might be declared in an interface.
 
-            if (current == null)
+            if (current == null || current == Object.class)
                 break;
         }
 
-        while (!interfaceQueue.isEmpty())
+        Iterator i = interfaceMethods.entrySet().iterator();
+        while (i.hasNext())
         {
-            Class thisInterface = (Class) interfaceQueue.remove(0);
+            Map.Entry entry = (Map.Entry) i.next();
+
+            MethodSignature sig = (MethodSignature) entry.getKey();
+
+            if (implementedMethods.contains(sig))
+                continue;
 
-            checkAllInterfaceMethodsImplemented(
-                    thisInterface,
+            Method method = (Method) entry.getValue();
+
+            _errorLog.error(EnhanceMessages.unimplementedInterfaceMethod(
+                    method,
                     baseClass,
-                    enhancedClass,
-                    implementedMethods,
-                    location);
+                    enhancedClass), location, null);
         }
 
     }
 
-    private void checkAllInterfaceMethodsImplemented(Class interfaceClass, Class baseClass,
-            Class enhancedClass, Set implementedMethods, Location location)
+    private void addInterfaceMethods(Class current, Map interfaceMethods)
     {
-        // Get all methods defined by the interface, or its super-interfaces
+        Class[] interfaces = current.getInterfaces();
+
+        for (int i = 0; i < interfaces.length; i++)
+            addMethodsFromInterface(interfaces[i], interfaceMethods);
+    }
 
+    private void addMethodsFromInterface(Class interfaceClass, Map interfaceMethods)
+    {
         Method[] methods = interfaceClass.getMethods();
 
         for (int i = 0; i < methods.length; i++)
         {
             MethodSignature sig = new MethodSignature(methods[i]);
 
-            if (!implementedMethods.contains(sig))
-                _errorLog.error(EnhanceMessages.unimplementedInterfaceMethod(
-                        methods[i],
-                        baseClass,
-                        enhancedClass), location, null);
+            if (interfaceMethods.containsKey(sig))
+                continue;
+
+            interfaceMethods.put(sig, methods[i]);
         }
     }
 



---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org