History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/reflect/Reflection.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/reflect/Reflection.java+325−0
@@ -0,0 +1,325 @@
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+
38+ /** Used to filter out fields and methods from certain classes from public
39+ view, where they are sensitive or they may contain VM-internal objects.
40+ These Maps are updated very rarely. Rather than synchronize on
41+ each access, we use copy-on-write */
42+ private static volatile Map<Class,String[]> fieldFilterMap;
43+ private static volatile Map<Class,String[]> methodFilterMap;
44+
45+ static {
46+ Map<Class,String[]> map = new HashMap<Class,String[]>();
47+ map.put(Reflection.class,
48+ new String[] {"fieldFilterMap", "methodFilterMap"});
49+ map.put(System.class, new String[] {"security"});
50+ fieldFilterMap = map;
51+
52+ methodFilterMap = new HashMap<Class,String[]>();
53+ }
54+
55+ /** Returns the class of the method <code>realFramesToSkip</code>
56+ frames up the stack (zero-based), ignoring frames associated
57+ with java.lang.reflect.Method.invoke() and its implementation.
58+ The first frame is that associated with this method, so
59+ <code>getCallerClass(0)</code> returns the Class object for
60+ sun.reflect.Reflection. Frames associated with
61+ java.lang.reflect.Method.invoke() and its implementation are
62+ completely ignored and do not count toward the number of "real"
63+ frames skipped. */
64+ public static native Class getCallerClass(int realFramesToSkip);
65+
66+ /** Retrieves the access flags written to the class file. For
67+ inner classes these flags may differ from those returned by
68+ Class.getModifiers(), which searches the InnerClasses
69+ attribute to find the source-level access flags. This is used
70+ instead of Class.getModifiers() for run-time access checks due
71+ to compatibility reasons; see 4471811. Only the values of the
72+ low 13 bits (i.e., a mask of 0x1FFF) are guaranteed to be
73+ valid. */
74+ private static native int getClassAccessFlags(Class c);
75+
76+ /** A quick "fast-path" check to try to avoid getCallerClass()
77+ calls. */
78+ public static boolean quickCheckMemberAccess(Class memberClass,
79+ int modifiers)
80+ {
81+ return Modifier.isPublic(getClassAccessFlags(memberClass) & modifiers);
82+ }
83+
84+ public static void ensureMemberAccess(Class currentClass,
85+ Class memberClass,
86+ Object target,
87+ int modifiers)
88+ throws IllegalAccessException
89+ {
90+ if (currentClass == null || memberClass == null) {
91+ throw new InternalError();
92+ }
93+
94+ if (!verifyMemberAccess(currentClass, memberClass, target, modifiers)) {
95+ throw new IllegalAccessException("Class " + currentClass.getName() +
96+ " can not access a member of class " +
97+ memberClass.getName() +
98+ " with modifiers \"" +
99+ Modifier.toString(modifiers) +
100+ "\"");
101+ }
102+ }
103+
104+ public static boolean verifyMemberAccess(Class currentClass,
105+ // Declaring class of field
106+ // or method
107+ Class memberClass,
108+ // May be NULL in case of statics
109+ Object target,
110+ int modifiers)
111+ {
112+ // Verify that currentClass can access a field, method, or
113+ // constructor of memberClass, where that member's access bits are
114+ // "modifiers".
115+
116+ boolean gotIsSameClassPackage = false;
117+ boolean isSameClassPackage = false;
118+
119+ if (currentClass == memberClass) {
120+ // Always succeeds
121+ return true;
122+ }
123+
124+ if (!Modifier.isPublic(getClassAccessFlags(memberClass))) {
125+ isSameClassPackage = isSameClassPackage(currentClass, memberClass);
126+ gotIsSameClassPackage = true;
127+ if (!isSameClassPackage) {
128+ return false;
129+ }
130+ }
131+
132+ // At this point we know that currentClass can access memberClass.
133+
134+ if (Modifier.isPublic(modifiers)) {
135+ return true;
136+ }
137+
138+ boolean successSoFar = false;
139+
140+ if (Modifier.isProtected(modifiers)) {
141+ // See if currentClass is a subclass of memberClass
142+ if (isSubclassOf(currentClass, memberClass)) {
143+ successSoFar = true;
144+ }
145+ }
146+
147+ if (!successSoFar && !Modifier.isPrivate(modifiers)) {
148+ if (!gotIsSameClassPackage) {
149+ isSameClassPackage = isSameClassPackage(currentClass,
150+ memberClass);
151+ gotIsSameClassPackage = true;
152+ }
153+
154+ if (isSameClassPackage) {
155+ successSoFar = true;
156+ }
157+ }
158+
159+ if (!successSoFar) {
160+ return false;
161+ }
162+
163+ if (Modifier.isProtected(modifiers)) {
164+ // Additional test for protected members: JLS 6.6.2
165+ Class targetClass = (target == null ? memberClass : target.getClass());
166+ if (targetClass != currentClass) {
167+ if (!gotIsSameClassPackage) {
168+ isSameClassPackage = isSameClassPackage(currentClass, memberClass);
169+ gotIsSameClassPackage = true;
170+ }
171+ if (!isSameClassPackage) {
172+ if (!isSubclassOf(targetClass, currentClass)) {
173+ return false;
174+ }
175+ }
176+ }
177+ }
178+
179+ return true;
180+ }
181+
182+ private static boolean isSameClassPackage(Class c1, Class c2) {
183+ return isSameClassPackage(c1.getClassLoader(), c1.getName(),
184+ c2.getClassLoader(), c2.getName());
185+ }
186+
187+ /** Returns true if two classes are in the same package; classloader
188+ and classname information is enough to determine a class's package */
189+ private static boolean isSameClassPackage(ClassLoader loader1, String name1,
190+ ClassLoader loader2, String name2)
191+ {
192+ if (loader1 != loader2) {
193+ return false;
194+ } else {
195+ int lastDot1 = name1.lastIndexOf('.');
196+ int lastDot2 = name2.lastIndexOf('.');
197+ if ((lastDot1 == -1) || (lastDot2 == -1)) {
198+ // One of the two doesn't have a package. Only return true
199+ // if the other one also doesn't have a package.
200+ return (lastDot1 == lastDot2);
201+ } else {
202+ int idx1 = 0;
203+ int idx2 = 0;
204+
205+ // Skip over '['s
206+ if (name1.charAt(idx1) == '[') {
207+ do {
208+ idx1++;
209+ } while (name1.charAt(idx1) == '[');
210+ if (name1.charAt(idx1) != 'L') {
211+ // Something is terribly wrong. Shouldn't be here.
212+ throw new InternalError("Illegal class name " + name1);
213+ }
214+ }
215+ if (name2.charAt(idx2) == '[') {
216+ do {
217+ idx2++;
218+ } while (name2.charAt(idx2) == '[');
219+ if (name2.charAt(idx2) != 'L') {
220+ // Something is terribly wrong. Shouldn't be here.
221+ throw new InternalError("Illegal class name " + name2);
222+ }
223+ }
224+
225+ // Check that package part is identical
226+ int length1 = lastDot1 - idx1;
227+ int length2 = lastDot2 - idx2;
228+
229+ if (length1 != length2) {
230+ return false;
231+ }
232+ return name1.regionMatches(false, idx1, name2, idx2, length1);
233+ }
234+ }
235+ }
236+
237+ static boolean isSubclassOf(Class queryClass,
238+ Class ofClass)
239+ {
240+ while (queryClass != null) {
241+ if (queryClass == ofClass) {
242+ return true;
243+ }
244+ queryClass = queryClass.getSuperclass();
245+ }
246+ return false;
247+ }
248+
249+ // fieldNames must contain only interned Strings
250+ public static synchronized void registerFieldsToFilter(Class containingClass,
251+ String ... fieldNames) {
252+ fieldFilterMap =
253+ registerFilter(fieldFilterMap, containingClass, fieldNames);
254+ }
255+
256+ // methodNames must contain only interned Strings
257+ public static synchronized void registerMethodsToFilter(Class containingClass,
258+ String ... methodNames) {
259+ methodFilterMap =
260+ registerFilter(methodFilterMap, containingClass, methodNames);
261+ }
262+
263+ private static Map<Class,String[]> registerFilter(Map<Class,String[]> map,
264+ Class containingClass, String ... names) {
265+ if (map.get(containingClass) != null) {
266+ throw new IllegalArgumentException
267+ ("Filter already registered: " + containingClass);
268+ }
269+ map = new HashMap<Class,String[]>(map);
270+ map.put(containingClass, names);
271+ return map;
272+ }
273+
274+ public static Field[] filterFields(Class containingClass,
275+ Field[] fields) {
276+ if (fieldFilterMap == null) {
277+ // Bootstrapping
278+ return fields;
279+ }
280+ return (Field[])filter(fields, fieldFilterMap.get(containingClass));
281+ }
282+
283+ public static Method[] filterMethods(Class containingClass, Method[] methods) {
284+ if (methodFilterMap == null) {
285+ // Bootstrapping
286+ return methods;
287+ }
288+ return (Method[])filter(methods, methodFilterMap.get(containingClass));
289+ }
290+
291+ private static Member[] filter(Member[] members, String[] filteredNames) {
292+ if ((filteredNames == null) || (members.length == 0)) {
293+ return members;
294+ }
295+ int numNewMembers = 0;
296+ for (Member member : members) {
297+ boolean shouldSkip = false;
298+ for (String filteredName : filteredNames) {
299+ if (member.getName() == filteredName) {
300+ shouldSkip = true;
301+ break;
302+ }
303+ }
304+ if (!shouldSkip) {
305+ ++numNewMembers;
306+ }
307+ }
308+ Member[] newMembers =
309+ (Member[])Array.newInstance(members[0].getClass(), numNewMembers);
310+ int destIdx = 0;
311+ for (Member member : members) {
312+ boolean shouldSkip = false;
313+ for (String filteredName : filteredNames) {
314+ if (member.getName() == filteredName) {
315+ shouldSkip = true;
316+ break;
317+ }
318+ }
319+ if (!shouldSkip) {
320+ newMembers[destIdx++] = member;
321+ }
322+ }
323+ return newMembers;
324+ }
325+}