1 /* 2 * Copyright (c) 2001, 2013, 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 38 // Android-removed: Dead code: Misc unused fields and methods. 39 40 public static void ensureMemberAccess(Class<?> currentClass, 41 Class<?> memberClass, 42 Object target, 43 int modifiers) 44 throws IllegalAccessException 45 { 46 if (currentClass == null || memberClass == null) { 47 throw new InternalError(); 48 } 49 50 if (!verifyMemberAccess(currentClass, memberClass, target, modifiers)) { 51 throw new IllegalAccessException("Class " + currentClass.getName() + 52 " can not access a member of class " + 53 memberClass.getName() + 54 " with modifiers \"" + 55 Modifier.toString(modifiers) + 56 "\""); 57 } 58 } 59 60 public static boolean verifyMemberAccess(Class<?> currentClass, 61 // Declaring class of field 62 // or method 63 Class<?> memberClass, 64 // May be NULL in case of statics 65 Object target, 66 int modifiers) 67 { 68 // Verify that currentClass can access a field, method, or 69 // constructor of memberClass, where that member's access bits are 70 // "modifiers". 71 72 boolean gotIsSameClassPackage = false; 73 boolean isSameClassPackage = false; 74 75 if (currentClass == memberClass) { 76 // Always succeeds 77 return true; 78 } 79 80 // Android-changed 81 // if (!Modifier.isPublic(getClassAccessFlags(memberClass))) { 82 if (!Modifier.isPublic(memberClass.getAccessFlags())) { 83 isSameClassPackage = isSameClassPackage(currentClass, memberClass); 84 gotIsSameClassPackage = true; 85 if (!isSameClassPackage) { 86 return false; 87 } 88 } 89 90 // At this point we know that currentClass can access memberClass. 91 92 if (Modifier.isPublic(modifiers)) { 93 return true; 94 } 95 96 boolean successSoFar = false; 97 98 if (Modifier.isProtected(modifiers)) { 99 // See if currentClass is a subclass of memberClass 100 if (isSubclassOf(currentClass, memberClass)) { 101 successSoFar = true; 102 } 103 } 104 105 if (!successSoFar && !Modifier.isPrivate(modifiers)) { 106 if (!gotIsSameClassPackage) { 107 isSameClassPackage = isSameClassPackage(currentClass, 108 memberClass); 109 gotIsSameClassPackage = true; 110 } 111 112 if (isSameClassPackage) { 113 successSoFar = true; 114 } 115 } 116 117 if (!successSoFar) { 118 return false; 119 } 120 121 if (Modifier.isProtected(modifiers)) { 122 // Additional test for protected members: JLS 6.6.2 123 Class<?> targetClass = (target == null ? memberClass : target.getClass()); 124 if (targetClass != currentClass) { 125 if (!gotIsSameClassPackage) { 126 isSameClassPackage = isSameClassPackage(currentClass, memberClass); 127 gotIsSameClassPackage = true; 128 } 129 if (!isSameClassPackage) { 130 if (!isSubclassOf(targetClass, currentClass)) { 131 return false; 132 } 133 } 134 } 135 } 136 137 return true; 138 } 139 140 private static boolean isSameClassPackage(Class<?> c1, Class<?> c2) { 141 return isSameClassPackage(c1.getClassLoader(), c1.getName(), 142 c2.getClassLoader(), c2.getName()); 143 } 144 145 /** Returns true if two classes are in the same package; classloader 146 and classname information is enough to determine a class's package */ 147 private static boolean isSameClassPackage(ClassLoader loader1, String name1, 148 ClassLoader loader2, String name2) 149 { 150 if (loader1 != loader2) { 151 return false; 152 } else { 153 int lastDot1 = name1.lastIndexOf('.'); 154 int lastDot2 = name2.lastIndexOf('.'); 155 if ((lastDot1 == -1) || (lastDot2 == -1)) { 156 // One of the two doesn't have a package. Only return true 157 // if the other one also doesn't have a package. 158 return (lastDot1 == lastDot2); 159 } else { 160 int idx1 = 0; 161 int idx2 = 0; 162 163 // Skip over '['s 164 if (name1.charAt(idx1) == '[') { 165 do { 166 idx1++; 167 } while (name1.charAt(idx1) == '['); 168 if (name1.charAt(idx1) != 'L') { 169 // Something is terribly wrong. Shouldn't be here. 170 throw new InternalError("Illegal class name " + name1); 171 } 172 } 173 if (name2.charAt(idx2) == '[') { 174 do { 175 idx2++; 176 } while (name2.charAt(idx2) == '['); 177 if (name2.charAt(idx2) != 'L') { 178 // Something is terribly wrong. Shouldn't be here. 179 throw new InternalError("Illegal class name " + name2); 180 } 181 } 182 183 // Check that package part is identical 184 int length1 = lastDot1 - idx1; 185 int length2 = lastDot2 - idx2; 186 187 if (length1 != length2) { 188 return false; 189 } 190 return name1.regionMatches(false, idx1, name2, idx2, length1); 191 } 192 } 193 } 194 195 static boolean isSubclassOf(Class<?> queryClass, 196 Class<?> ofClass) 197 { 198 while (queryClass != null) { 199 if (queryClass == ofClass) { 200 return true; 201 } 202 queryClass = queryClass.getSuperclass(); 203 } 204 return false; 205 } 206 207 // Android-removed: Dead code: Misc unused methods. 208 209 } 210