Skip to content

Commit ad54257

Browse files
hansonrhansonr
authored andcommitted
sun.reflect.Reflection.getCallingClass
1 parent 4e683a6 commit ad54257

File tree

1 file changed

+375
-0
lines changed

1 file changed

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

0 commit comments

Comments
 (0)