• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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