Coverage Report - org.apache.tapestry.enhance.EnhancedClassValidatorImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
EnhancedClassValidatorImpl
0%
0/49
0%
0/24
3
 
 1  
 // Copyright 2004, 2005 The Apache Software Foundation
 2  
 //
 3  
 // Licensed under the Apache License, Version 2.0 (the "License");
 4  
 // you may not use this file except in compliance with the License.
 5  
 // You may obtain a copy of the License at
 6  
 //
 7  
 //     http://www.apache.org/licenses/LICENSE-2.0
 8  
 //
 9  
 // Unless required by applicable law or agreed to in writing, software
 10  
 // distributed under the License is distributed on an "AS IS" BASIS,
 11  
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12  
 // See the License for the specific language governing permissions and
 13  
 // limitations under the License.
 14  
 
 15  
 package org.apache.tapestry.enhance;
 16  
 
 17  
 import java.lang.reflect.Method;
 18  
 import java.lang.reflect.Modifier;
 19  
 import java.util.HashMap;
 20  
 import java.util.HashSet;
 21  
 import java.util.Iterator;
 22  
 import java.util.List;
 23  
 import java.util.Map;
 24  
 import java.util.Set;
 25  
 
 26  
 import org.apache.hivemind.ErrorLog;
 27  
 import org.apache.hivemind.Location;
 28  
 import org.apache.tapestry.spec.IComponentSpecification;
 29  
 
 30  
 /**
 31  
  * Validates that an enhanced class is correct; checks that all inherited
 32  
  * abstract methods are, in fact, implemented in the class.
 33  
  * 
 34  
  * @author Howard M. Lewis Ship
 35  
  * @since 4.0
 36  
  */
 37  0
 public class EnhancedClassValidatorImpl implements EnhancedClassValidator
 38  
 {
 39  
 
 40  
     private ErrorLog _errorLog;
 41  
 
 42  
     private ClassInspector _inspector;
 43  
     
 44  
     public void validate(Class baseClass, Class enhancedClass, IComponentSpecification specification)
 45  
     {
 46  
         // Set of MethodSignatures for methods that have a non-abstract
 47  
         // implementation
 48  
         // The Set is built working from the deepest subclass up to (and
 49  
         // including) java.lang.Object
 50  
 
 51  0
         Set implementedMethods = new HashSet();
 52  
         // Key is MethodSignature, value is Method
 53  
         // Tracks which methods come from interfaces
 54  0
         Map interfaceMethods = new HashMap();
 55  
 
 56  0
         Location location = specification.getLocation();
 57  
 
 58  0
         Class current = enhancedClass;
 59  
 
 60  
         while(true)
 61  
         {
 62  0
             addInterfaceMethods(current, interfaceMethods);
 63  
 
 64  
             // Inside Eclipse, for abstract classes, getDeclaredMethods() does
 65  
             // NOT report methods
 66  
             // inherited from interfaces. For Sun JDK and abstract classes,
 67  
             // getDeclaredMethods()
 68  
             // DOES report interface methods
 69  
             // (as if they were declared by the class itself). This code is
 70  
             // needlessly complex so
 71  
             // that the checks work in both
 72  
             // situations. Basically, I think Eclipse is right and Sun JDK is
 73  
             // wrong and we're using
 74  
             // the interfaceMethods map as a filter to ignore methods that Sun
 75  
             // JDK is attributing
 76  
             // to the class.
 77  
 
 78  0
             Method[] methods = current.getDeclaredMethods();
 79  
 
 80  0
             for(int i = 0; i < methods.length; i++)
 81  
             {
 82  0
                 Method m = methods[i];
 83  
 
 84  0
                 MethodSignature s = _inspector.getMethodSignature(current, m);
 85  
 
 86  0
                 boolean isAbstract = Modifier.isAbstract(m.getModifiers());
 87  
                 
 88  0
                 if (isAbstract)
 89  
                 {
 90  0
                     if (interfaceMethods.containsKey(s)) 
 91  0
                         continue;
 92  
 
 93  
                     // If a superclass defines an abstract method that a
 94  
                     // subclass implements, then
 95  
                     // all's OK.
 96  
 
 97  0
                     if (implementedMethods.contains(s)) 
 98  0
                         continue;
 99  
                     
 100  0
                     _errorLog.error(EnhanceMessages.noImplForAbstractMethod(m, current, baseClass, enhancedClass), location, null);
 101  
                 }
 102  
 
 103  0
                 implementedMethods.add(s);
 104  
             }
 105  
 
 106  0
             current = current.getSuperclass();
 107  
 
 108  
             // No need to check Object.class; it is concrete and doesn't
 109  
             // implement any interfaces,
 110  
             // or provide any methods
 111  
             // that might be declared in an interface.
 112  
 
 113  0
             if (current == null || current == Object.class) 
 114  0
                 break;
 115  0
         }
 116  
 
 117  0
         Iterator i = interfaceMethods.entrySet().iterator();
 118  0
         while(i.hasNext())
 119  
         {
 120  0
             Map.Entry entry = (Map.Entry) i.next();
 121  
 
 122  0
             MethodSignature sig = (MethodSignature) entry.getKey();
 123  
 
 124  0
             if (implementedMethods.contains(sig)) 
 125  0
                 continue;
 126  
 
 127  0
             Method method = (Method) entry.getValue();
 128  
 
 129  0
             _errorLog.error(EnhanceMessages.unimplementedInterfaceMethod(method, baseClass, enhancedClass), location, null);
 130  0
         }
 131  
 
 132  0
     }
 133  
 
 134  
     private void addInterfaceMethods(Class current, Map interfaceMethods)
 135  
     {
 136  0
         Class[] interfaces = current.getInterfaces();
 137  
 
 138  0
         for(int i = 0; i < interfaces.length; i++)
 139  0
             addMethodsFromInterface(interfaces[i], interfaceMethods);
 140  0
     }
 141  
 
 142  
     private void addMethodsFromInterface(Class interfaceClass, Map interfaceMethods)
 143  
     {
 144  0
         Method[] methods = interfaceClass.getMethods();
 145  
 
 146  0
         for(int i = 0; i < methods.length; i++)
 147  
         {
 148  0
             MethodSignature sig = _inspector.getMethodSignature(interfaceClass, methods[i]);
 149  
             
 150  0
             if (interfaceMethods.containsKey(sig)) 
 151  0
                 continue;
 152  
             
 153  0
             interfaceMethods.put(sig, methods[i]);
 154  
         }
 155  0
     }
 156  
 
 157  
     public void setErrorLog(ErrorLog errorLog)
 158  
     {
 159  0
         _errorLog = errorLog;
 160  0
     }
 161  
     
 162  
     public void setClassInspector(ClassInspector inspector)
 163  
     {
 164  0
         _inspector = inspector;
 165  0
     }
 166  
     
 167  
     public void setClassInspectors(List inspectors)
 168  
     {
 169  0
         _inspector = (ClassInspector)inspectors.get(0);
 170  0
     }
 171  
 }