1 /*
   2  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 import java.lang.reflect.Method;
  25 import java.lang.reflect.Modifier;
  26 import java.util.ArrayList;
  27 import java.util.Arrays;
  28 import java.util.Dictionary;
  29 import java.util.Hashtable;
  30 import java.util.List;
  31 import java.util.Map;
  32 import java.util.Properties;
  33 
  34 /*
  35  * @test
  36  * @bug 8029891
  37  * @summary Test that the Properties class overrides all public+protected
  38  *          methods of all ancestor classes and interfaces
  39  * @run main CheckOverrides
  40  * @author bchristi
  41  */
  42 public class CheckOverrides {
  43     private static List<SameMethodNoClass> pMethods;
  44 
  45     private static boolean isMethodOfInterest(Method method) {
  46         int mods = method.getModifiers();
  47         return !Modifier.isStatic(mods) &&
  48                (Modifier.isPublic(mods) || Modifier.isProtected(mods));
  49     }    
  50     
  51     public static void main(String[] args) {
  52         // Create list of all non-static, public/protected Properties methods 
  53         Class propsClass = Properties.class;
  54         Method[] pMethodArray = propsClass.getDeclaredMethods();
  55         pMethods = new ArrayList<>(pMethodArray.length);
  56 
  57         for (Method method : pMethodArray ) {
  58             if (isMethodOfInterest(method)) {
  59                 pMethods.add(new SameMethodNoClass(method));
  60             }
  61         }
  62         System.out.println(pMethods.size() + " non-static, public/protected"
  63                 + " methods in " + propsClass);
  64 
  65         // Assemble list of all interfaces and classes to check
  66         List<Class> classesToCheck = new ArrayList<>();
  67         classesToCheck.addAll(Arrays.asList(propsClass.getInterfaces()));
  68         
  69         Class superClass = propsClass.getSuperclass();
  70         while (!superClass.equals(Object.class)) {
  71             classesToCheck.add(superClass);
  72             classesToCheck.addAll(Arrays.asList(superClass.getInterfaces()));
  73             superClass = superClass.getSuperclass();            
  74         }
  75         
  76         boolean passed = true;
  77         for (Class toCheck : classesToCheck) {
  78             passed = checkClass(toCheck) && passed;               
  79         }        
  80         if (!passed) {
  81             throw new RuntimeException("Test failed");
  82         }
  83         System.out.println("Test passed");        
  84     }
  85     
  86     /**
  87      * Check Properties for methods in the given class.
  88      * Return true if all found, false otherwise
  89      */
  90     private static boolean checkClass(Class clazz) {
  91         boolean passed = true;
  92         // For each non-static, public/protected method, confirm
  93         // that it's in the list.
  94         Method[] methods = clazz.getDeclaredMethods();
  95         int numPubProcMethods = 0;
  96                 
  97         for (Method method : methods) {
  98             if (isMethodOfInterest(method)) {
  99                 numPubProcMethods++;
 100                 boolean contains = pMethods.contains(new
 101                                                      SameMethodNoClass(method));
 102                 if (!contains) {
 103                     passed = false;
 104                     System.out.println("Properties does not contain: " + method);
 105                     System.out.println("                       from: " + clazz);
 106                 }
 107             }
 108         }        
 109         System.out.println("Checked " + numPubProcMethods + " public/protected "
 110                 + "methods in " + clazz);
 111         return passed;
 112     }
 113     
 114     /*
 115      * Wrapper to compare Methods, ignoring declaring Class
 116      */
 117     private static class SameMethodNoClass {
 118         public Method method;
 119         public SameMethodNoClass(Method method) { this.method = method; }
 120         
 121         @Override
 122         public boolean equals(Object other) {
 123             if (other instanceof SameMethodNoClass) {
 124                 SameMethodNoClass smnc = (SameMethodNoClass)other;
 125                 
 126                 return this.method.getName().equals(smnc.method.getName()) &&
 127                        this.method.getReturnType().equals(smnc.method.getReturnType()) &&
 128                        Arrays.equals(this.method.getParameterTypes(),
 129                                      smnc.method.getParameterTypes()) &&
 130                        Arrays.equals(this.method.getExceptionTypes(),
 131                                      smnc.method.getExceptionTypes());                   
 132             }
 133             return false;
 134         }
 135         @Override
 136         public int hashCode() { return method.hashCode(); }        
 137         @Override
 138         public String toString() { return method.toString(); }
 139     }
 140 }