1 /* 2 * Copyright (c) 2001, 2006, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.reflect; 27 28 import java.lang.reflect.*; 29 import java.util.Collections; 30 import java.util.HashMap; 31 import java.util.Map; 32 33 /** Common utility routines used by both java.lang and 34 java.lang.reflect */ 35 36 public class Reflection { 37 ensureMemberAccess(Class currentClass, Class memberClass, Object target, int modifiers)38 public static void ensureMemberAccess(Class currentClass, 39 Class memberClass, 40 Object target, 41 int modifiers) 42 throws IllegalAccessException 43 { 44 if (currentClass == null || memberClass == null) { 45 throw new InternalError(); 46 } 47 48 if (!verifyMemberAccess(currentClass, memberClass, target, modifiers)) { 49 throw new IllegalAccessException("Class " + currentClass.getName() + 50 " can not access a member of class " + 51 memberClass.getName() + 52 " with modifiers \"" + 53 Modifier.toString(modifiers) + 54 "\""); 55 } 56 } 57 verifyMemberAccess(Class currentClass, Class memberClass, Object target, int modifiers)58 public static boolean verifyMemberAccess(Class currentClass, 59 // Declaring class of field 60 // or method 61 Class memberClass, 62 // May be NULL in case of statics 63 Object target, 64 int modifiers) 65 { 66 // Verify that currentClass can access a field, method, or 67 // constructor of memberClass, where that member's access bits are 68 // "modifiers". 69 70 boolean gotIsSameClassPackage = false; 71 boolean isSameClassPackage = false; 72 73 if (currentClass == memberClass) { 74 // Always succeeds 75 return true; 76 } 77 78 /* ----- BEGIN android ----- 79 if (!Modifier.isPublic(getClassAccessFlags(memberClass))) {*/ 80 if (!Modifier.isPublic(memberClass.getAccessFlags())) { 81 // ----- END android ----- 82 isSameClassPackage = isSameClassPackage(currentClass, memberClass); 83 gotIsSameClassPackage = true; 84 if (!isSameClassPackage) { 85 return false; 86 } 87 } 88 89 // At this point we know that currentClass can access memberClass. 90 91 if (Modifier.isPublic(modifiers)) { 92 return true; 93 } 94 95 boolean successSoFar = false; 96 97 if (Modifier.isProtected(modifiers)) { 98 // See if currentClass is a subclass of memberClass 99 if (isSubclassOf(currentClass, memberClass)) { 100 successSoFar = true; 101 } 102 } 103 104 if (!successSoFar && !Modifier.isPrivate(modifiers)) { 105 if (!gotIsSameClassPackage) { 106 isSameClassPackage = isSameClassPackage(currentClass, 107 memberClass); 108 gotIsSameClassPackage = true; 109 } 110 111 if (isSameClassPackage) { 112 successSoFar = true; 113 } 114 } 115 116 if (!successSoFar) { 117 return false; 118 } 119 120 if (Modifier.isProtected(modifiers)) { 121 // Additional test for protected members: JLS 6.6.2 122 Class targetClass = (target == null ? memberClass : target.getClass()); 123 if (targetClass != currentClass) { 124 if (!gotIsSameClassPackage) { 125 isSameClassPackage = isSameClassPackage(currentClass, memberClass); 126 gotIsSameClassPackage = true; 127 } 128 if (!isSameClassPackage) { 129 if (!isSubclassOf(targetClass, currentClass)) { 130 return false; 131 } 132 } 133 } 134 } 135 136 return true; 137 } 138 isSameClassPackage(Class c1, Class c2)139 private static boolean isSameClassPackage(Class c1, Class c2) { 140 return isSameClassPackage(c1.getClassLoader(), c1.getName(), 141 c2.getClassLoader(), c2.getName()); 142 } 143 144 /** Returns true if two classes are in the same package; classloader 145 and classname information is enough to determine a class's package */ isSameClassPackage(ClassLoader loader1, String name1, ClassLoader loader2, String name2)146 private static boolean isSameClassPackage(ClassLoader loader1, String name1, 147 ClassLoader loader2, String name2) 148 { 149 if (loader1 != loader2) { 150 return false; 151 } else { 152 int lastDot1 = name1.lastIndexOf('.'); 153 int lastDot2 = name2.lastIndexOf('.'); 154 if ((lastDot1 == -1) || (lastDot2 == -1)) { 155 // One of the two doesn't have a package. Only return true 156 // if the other one also doesn't have a package. 157 return (lastDot1 == lastDot2); 158 } else { 159 int idx1 = 0; 160 int idx2 = 0; 161 162 // Skip over '['s 163 if (name1.charAt(idx1) == '[') { 164 do { 165 idx1++; 166 } while (name1.charAt(idx1) == '['); 167 if (name1.charAt(idx1) != 'L') { 168 // Something is terribly wrong. Shouldn't be here. 169 throw new InternalError("Illegal class name " + name1); 170 } 171 } 172 if (name2.charAt(idx2) == '[') { 173 do { 174 idx2++; 175 } while (name2.charAt(idx2) == '['); 176 if (name2.charAt(idx2) != 'L') { 177 // Something is terribly wrong. Shouldn't be here. 178 throw new InternalError("Illegal class name " + name2); 179 } 180 } 181 182 // Check that package part is identical 183 int length1 = lastDot1 - idx1; 184 int length2 = lastDot2 - idx2; 185 186 if (length1 != length2) { 187 return false; 188 } 189 return name1.regionMatches(false, idx1, name2, idx2, length1); 190 } 191 } 192 } 193 isSubclassOf(Class queryClass, Class ofClass)194 static boolean isSubclassOf(Class queryClass, 195 Class ofClass) 196 { 197 while (queryClass != null) { 198 if (queryClass == ofClass) { 199 return true; 200 } 201 queryClass = queryClass.getSuperclass(); 202 } 203 return false; 204 } 205 } 206