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
26package sun.reflect.misc;
27
28import java.security.AllPermission;
29import java.security.AccessController;
30import java.security.PermissionCollection;
31import java.security.SecureClassLoader;
32import java.security.PrivilegedExceptionAction;
33import java.security.CodeSource;
34import java.io.InputStream;
35import java.io.BufferedInputStream;
36import java.io.IOException;
37import java.net.URL;
38import java.net.URLConnection;
39import java.net.HttpURLConnection;
40import java.lang.reflect.Method;
41import java.lang.reflect.InvocationTargetException;
42import java.lang.reflect.AccessibleObject;
43import java.lang.reflect.Modifier;
44import java.util.Collection;
45import java.util.HashMap;
46import java.util.Map;
47import sun.misc.IOUtils;
48import sun.net.www.ParseUtil;
49import sun.security.util.SecurityConstants;
50
51
52class 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 */
62public 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}