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/misc/MethodUtil.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/reflect/misc/MethodUtil.java+400−0
@@ -0,0 +1,400 @@
1+/*
2+ * Copyright (c) 2005, 2009, 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.misc;
27+
28+import java.security.AllPermission;
29+import java.security.AccessController;
30+import java.security.PermissionCollection;
31+import java.security.SecureClassLoader;
32+import java.security.PrivilegedExceptionAction;
33+import java.security.CodeSource;
34+import java.io.InputStream;
35+import java.io.BufferedInputStream;
36+import java.io.IOException;
37+import java.net.URL;
38+import java.net.URLConnection;
39+import java.net.HttpURLConnection;
40+import java.lang.reflect.Method;
41+import java.lang.reflect.InvocationTargetException;
42+import java.lang.reflect.AccessibleObject;
43+import java.lang.reflect.Modifier;
44+import java.util.Collection;
45+import java.util.HashMap;
46+import java.util.Map;
47+import sun.misc.IOUtils;
48+import sun.net.www.ParseUtil;
49+import sun.security.util.SecurityConstants;
50+
51+
52+class Trampoline {
53+ private static Object invoke(Method m, Object obj, Object[] params)
54+ throws InvocationTargetException, IllegalAccessException {
55+ return m.invoke(obj, params);
56+ }
57+}
58+
59+/*
60+ * Create a trampoline class.
61+ */
62+public final class MethodUtil extends SecureClassLoader {
63+ private static String MISC_PKG = "sun.reflect.misc.";
64+ private static String TRAMPOLINE = MISC_PKG + "Trampoline";
65+ private static Method bounce = getTrampoline();
66+
67+ private MethodUtil() {
68+ super();
69+ }
70+
71+ public static Method getMethod(Class<?> cls, String name, Class[] args)
72+ throws NoSuchMethodException {
73+ ReflectUtil.checkPackageAccess(cls);
74+ return cls.getMethod(name, args);
75+ }
76+
77+ public static Method[] getMethods(Class cls) {
78+ ReflectUtil.checkPackageAccess(cls);
79+ return cls.getMethods();
80+ }
81+
82+ /*
83+ * Discover the public methods on public classes
84+ * and interfaces accessible to any caller by calling
85+ * Class.getMethods() and walking towards Object until
86+ * we're done.
87+ */
88+ public static Method[] getPublicMethods(Class cls) {
89+ // compatibility for update release
90+ if (System.getSecurityManager() == null) {
91+ return cls.getMethods();
92+ }
93+ Map<Signature, Method> sigs = new HashMap<Signature, Method>();
94+ while (cls != null) {
95+ boolean done = getInternalPublicMethods(cls, sigs);
96+ if (done) {
97+ break;
98+ }
99+ getInterfaceMethods(cls, sigs);
100+ cls = cls.getSuperclass();
101+ }
102+ return sigs.values().toArray(new Method[sigs.size()]);
103+ }
104+
105+ /*
106+ * Process the immediate interfaces of this class or interface.
107+ */
108+ private static void getInterfaceMethods(Class cls,
109+ Map<Signature, Method> sigs) {
110+ Class[] intfs = cls.getInterfaces();
111+ for (int i=0; i < intfs.length; i++) {
112+ Class intf = intfs[i];
113+ boolean done = getInternalPublicMethods(intf, sigs);
114+ if (!done) {
115+ getInterfaceMethods(intf, sigs);
116+ }
117+ }
118+ }
119+
120+ /*
121+ *
122+ * Process the methods in this class or interface
123+ */
124+ private static boolean getInternalPublicMethods(Class cls,
125+ Map<Signature, Method> sigs) {
126+ Method[] methods = null;
127+ try {
128+ /*
129+ * This class or interface is non-public so we
130+ * can't use any of it's methods. Go back and
131+ * try again with a superclass or superinterface.
132+ */
133+ if (!Modifier.isPublic(cls.getModifiers())) {
134+ return false;
135+ }
136+ if (!ReflectUtil.isPackageAccessible(cls)) {
137+ return false;
138+ }
139+
140+ methods = cls.getMethods();
141+ } catch (SecurityException se) {
142+ return false;
143+ }
144+
145+ /*
146+ * Check for inherited methods with non-public
147+ * declaring classes. They might override and hide
148+ * methods from their superclasses or
149+ * superinterfaces.
150+ */
151+ boolean done = true;
152+ for (int i=0; i < methods.length; i++) {
153+ Class dc = methods[i].getDeclaringClass();
154+ if (!Modifier.isPublic(dc.getModifiers())) {
155+ done = false;
156+ break;
157+ }
158+ }
159+
160+ if (done) {
161+ /*
162+ * We're done. Spray all the methods into
163+ * the list and then we're out of here.
164+ */
165+ for (int i=0; i < methods.length; i++) {
166+ addMethod(sigs, methods[i]);
167+ }
168+ } else {
169+ /*
170+ * Simulate cls.getDeclaredMethods() by
171+ * stripping away inherited methods.
172+ */
173+ for (int i=0; i < methods.length; i++) {
174+ Class dc = methods[i].getDeclaringClass();
175+ if (cls.equals(dc)) {
176+ addMethod(sigs, methods[i]);
177+ }
178+ }
179+ }
180+ return done;
181+ }
182+
183+ private static void addMethod(Map<Signature, Method> sigs, Method method) {
184+ Signature signature = new Signature(method);
185+ if (!sigs.containsKey(signature)) {
186+ sigs.put(signature, method);
187+ } else if (!method.getDeclaringClass().isInterface()){
188+ /*
189+ * Superclasses beat interfaces.
190+ */
191+ Method old = sigs.get(signature);
192+ if (old.getDeclaringClass().isInterface()) {
193+ sigs.put(signature, method);
194+ }
195+ }
196+ }
197+
198+ /**
199+ * A class that represents the unique elements of a method that will be a
200+ * key in the method cache.
201+ */
202+ private static class Signature {
203+ private String methodName;
204+ private Class[] argClasses;
205+
206+ private volatile int hashCode = 0;
207+
208+ Signature(Method m) {
209+ this.methodName = m.getName();
210+ this.argClasses = m.getParameterTypes();
211+ }
212+
213+ public boolean equals(Object o2) {
214+ if (this == o2) {
215+ return true;
216+ }
217+ Signature that = (Signature)o2;
218+ if (!(methodName.equals(that.methodName))) {
219+ return false;
220+ }
221+ if (argClasses.length != that.argClasses.length) {
222+ return false;
223+ }
224+ for (int i = 0; i < argClasses.length; i++) {
225+ if (!(argClasses[i] == that.argClasses[i])) {
226+ return false;
227+ }
228+ }
229+ return true;
230+ }
231+
232+ /**
233+ * Hash code computed using algorithm suggested in
234+ * Effective Java, Item 8.
235+ */
236+ public int hashCode() {
237+ if (hashCode == 0) {
238+ int result = 17;
239+ result = 37 * result + methodName.hashCode();
240+ if (argClasses != null) {
241+ for (int i = 0; i < argClasses.length; i++) {
242+ result = 37 * result + ((argClasses[i] == null) ? 0 :
243+ argClasses[i].hashCode());
244+ }
245+ }
246+ hashCode = result;
247+ }
248+ return hashCode;
249+ }
250+ }
251+
252+
253+ /*
254+ * Bounce through the trampoline.
255+ */
256+ public static Object invoke(Method m, Object obj, Object[] params)
257+ throws InvocationTargetException, IllegalAccessException {
258+ if (m.getDeclaringClass().equals(AccessController.class) ||
259+ m.getDeclaringClass().equals(Method.class))
260+ throw new InvocationTargetException(
261+ new UnsupportedOperationException("invocation not supported"));
262+ try {
263+ return bounce.invoke(null, new Object[] {m, obj, params});
264+ } catch (InvocationTargetException ie) {
265+ Throwable t = ie.getCause();
266+
267+ if (t instanceof InvocationTargetException) {
268+ throw (InvocationTargetException)t;
269+ } else if (t instanceof IllegalAccessException) {
270+ throw (IllegalAccessException)t;
271+ } else if (t instanceof RuntimeException) {
272+ throw (RuntimeException)t;
273+ } else if (t instanceof Error) {
274+ throw (Error)t;
275+ } else {
276+ throw new Error("Unexpected invocation error", t);
277+ }
278+ } catch (IllegalAccessException iae) {
279+ // this can't happen
280+ throw new Error("Unexpected invocation error", iae);
281+ }
282+ }
283+
284+ private static Method getTrampoline() {
285+ try {
286+ return AccessController.doPrivileged(
287+ new PrivilegedExceptionAction<Method>() {
288+ public Method run() throws Exception {
289+ Class<?> t = getTrampolineClass();
290+ Class[] types = {
291+ Method.class, Object.class, Object[].class
292+ };
293+ Method b = t.getDeclaredMethod("invoke", types);
294+ ((AccessibleObject)b).setAccessible(true);
295+ return b;
296+ }
297+ });
298+ } catch (Exception e) {
299+ throw new InternalError("bouncer cannot be found");
300+ }
301+ }
302+
303+
304+ protected synchronized Class loadClass(String name, boolean resolve)
305+ throws ClassNotFoundException
306+ {
307+ // First, check if the class has already been loaded
308+ ReflectUtil.checkPackageAccess(name);
309+ Class c = findLoadedClass(name);
310+ if (c == null) {
311+ try {
312+ c = findClass(name);
313+ } catch (ClassNotFoundException e) {
314+ // Fall through ...
315+ }
316+ if (c == null) {
317+ c = getParent().loadClass(name);
318+ }
319+ }
320+ if (resolve) {
321+ resolveClass(c);
322+ }
323+ return c;
324+ }
325+
326+
327+ protected Class findClass(final String name)
328+ throws ClassNotFoundException
329+ {
330+ if (!name.startsWith(MISC_PKG)) {
331+ throw new ClassNotFoundException(name);
332+ }
333+ String path = name.replace('.', '/').concat(".class");
334+ URL res = getResource(path);
335+ if (res != null) {
336+ try {
337+ return defineClass(name, res);
338+ } catch (IOException e) {
339+ throw new ClassNotFoundException(name, e);
340+ }
341+ } else {
342+ throw new ClassNotFoundException(name);
343+ }
344+ }
345+
346+
347+ /*
348+ * Define the proxy classes
349+ */
350+ private Class defineClass(String name, URL url) throws IOException {
351+ byte[] b = getBytes(url);
352+ CodeSource cs = new CodeSource(null, (java.security.cert.Certificate[])null);
353+ if (!name.equals(TRAMPOLINE)) {
354+ throw new IOException("MethodUtil: bad name " + name);
355+ }
356+ return defineClass(name, b, 0, b.length, cs);
357+ }
358+
359+
360+ /*
361+ * Returns the contents of the specified URL as an array of bytes.
362+ */
363+ private static byte[] getBytes(URL url) throws IOException {
364+ URLConnection uc = url.openConnection();
365+ if (uc instanceof java.net.HttpURLConnection) {
366+ java.net.HttpURLConnection huc = (java.net.HttpURLConnection) uc;
367+ int code = huc.getResponseCode();
368+ if (code >= java.net.HttpURLConnection.HTTP_BAD_REQUEST) {
369+ throw new IOException("open HTTP connection failed.");
370+ }
371+ }
372+ int len = uc.getContentLength();
373+ InputStream in = new BufferedInputStream(uc.getInputStream());
374+
375+ byte[] b;
376+ try {
377+ b = IOUtils.readFully(in, len, true);
378+ } finally {
379+ in.close();
380+ }
381+ return b;
382+ }
383+
384+
385+ protected PermissionCollection getPermissions(CodeSource codesource)
386+ {
387+ PermissionCollection perms = super.getPermissions(codesource);
388+ perms.add(new AllPermission());
389+ return perms;
390+ }
391+
392+ private static Class getTrampolineClass() {
393+ try {
394+ return Class.forName(TRAMPOLINE, true, new MethodUtil());
395+ } catch (ClassNotFoundException e) {
396+ }
397+ return null;
398+ }
399+
400+}