mirror of
https://git.freebsd.org/ports.git
synced 2025-06-08 06:10:30 -04:00
312 lines
8.2 KiB
Java
312 lines
8.2 KiB
Java
$FreeBSD$
|
|
|
|
--- ../../deploy/src/plugin/src/share/classes/sun/plugin/javascript/ReflectUtil.java 1 Jan 1970 00:00:00 -0000
|
|
+++ ../../deploy/src/plugin/src/share/classes/sun/plugin/javascript/ReflectUtil.java 3 Dec 2004 03:56:58 -0000 1.1
|
|
@@ -0,0 +1,307 @@
|
|
+/*
|
|
+ * @(#)ReflectUtil.java 1.1 04/06/20
|
|
+ *
|
|
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
|
+ * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
|
+ */
|
|
+package sun.plugin.javascript;
|
|
+
|
|
+import java.lang.reflect.Method;
|
|
+import java.lang.reflect.Field;
|
|
+import java.lang.reflect.Modifier;
|
|
+import java.lang.reflect.InvocationTargetException;
|
|
+import java.util.HashMap;
|
|
+import java.util.ArrayList;
|
|
+import java.util.List;
|
|
+import java.util.Map;
|
|
+import java.util.Iterator;
|
|
+import sun.plugin.javascript.JSClassLoader;
|
|
+
|
|
+public class ReflectUtil {
|
|
+ /*
|
|
+ * Discover the public methods on public classes
|
|
+ * and interfaces accessible to the calling
|
|
+ * JavaScript code.
|
|
+ */
|
|
+ public static Method[] getJScriptMethods(Class cls) {
|
|
+ List m = new ArrayList(); /* the valid methods we find */
|
|
+
|
|
+ /*
|
|
+ * Temporary map of method signatures when we decide
|
|
+ * that a simple call to target.getMethods() returns
|
|
+ * inaccessible methods and we must search for alternative
|
|
+ * supermethods that might be accessible. We can toss
|
|
+ * this when we're done searching.
|
|
+ */
|
|
+ Map sigs = new HashMap();
|
|
+
|
|
+ while (cls != null) {
|
|
+ boolean done = getPublicMethods(cls, m, sigs);
|
|
+ if (done) {
|
|
+ break;
|
|
+ }
|
|
+ getJScriptInterfaceMethods(cls, m, sigs);
|
|
+ cls = cls.getSuperclass();
|
|
+ }
|
|
+ return (Method[]) m.toArray(new Method[m.size()]);
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Process the immediate interfaces of this class or interface.
|
|
+ */
|
|
+ private static void getJScriptInterfaceMethods(Class cls, List m, Map sigs) {
|
|
+ Class[] intfs = cls.getInterfaces();
|
|
+ for (int i=0; i < intfs.length; i++) {
|
|
+ Class intf = intfs[i];
|
|
+ boolean done = getPublicMethods(intf, m, sigs);
|
|
+ if (!done) {
|
|
+ getJScriptInterfaceMethods(intf, m, sigs);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ *
|
|
+ * Process the methods in this class or interface
|
|
+ */
|
|
+ private static boolean getPublicMethods(Class cls, List m, Map sigs) {
|
|
+ Method[] methods = null;
|
|
+ try {
|
|
+
|
|
+ /*
|
|
+ * This class or interface is non-public so we
|
|
+ * can't use any of it's methods. Go back and
|
|
+ * try again with a superclass or superinterface.
|
|
+ */
|
|
+ if (!Modifier.isPublic(cls.getModifiers())) {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if (!JSClassLoader.isPackageAccessible(cls)) {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ methods = cls.getMethods();
|
|
+ } catch (SecurityException se) {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Check for inherited methods with non-public
|
|
+ * declaring classes. They might override and hide
|
|
+ * methods from their superclasses or
|
|
+ * superinterfaces.
|
|
+ */
|
|
+ boolean done = true;
|
|
+ for (int i=0; i < methods.length; i++) {
|
|
+ Class dc = methods[i].getDeclaringClass();
|
|
+ if (!Modifier.isPublic(dc.getModifiers())) {
|
|
+ done = false;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Belatedly initialize the signature map if
|
|
+ * this is not the first time here.
|
|
+ */
|
|
+ if (sigs.isEmpty() && !m.isEmpty()) {
|
|
+ initSignatureMap(m, sigs);
|
|
+ }
|
|
+
|
|
+ if (done) {
|
|
+ /*
|
|
+ * We're done. Spray all the methods into
|
|
+ * the list and then we're out of here.
|
|
+ */
|
|
+ for (int i=0; i < methods.length; i++) {
|
|
+ addMethod(m, sigs, methods[i]);
|
|
+ }
|
|
+ } else {
|
|
+ /*
|
|
+ * Simulate cls.getDeclaredMethods() by
|
|
+ * stripping away inherited methods.
|
|
+ */
|
|
+ for (int i=0; i < methods.length; i++) {
|
|
+ Class dc = methods[i].getDeclaringClass();
|
|
+ if (cls.equals(dc)) {
|
|
+ addMethod(m, sigs, methods[i]);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return done;
|
|
+ }
|
|
+
|
|
+ private static void initSignatureMap(List m, Map sigs) {
|
|
+ Iterator i = m.iterator();
|
|
+ while (i.hasNext()) {
|
|
+ Method entry = (Method) i.next();
|
|
+ sigs.put(getSignature(entry), entry);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private static void addMethod(List m, Map sigs, Method method) {
|
|
+ /*
|
|
+ * Avoid work. We ignore the signature matching
|
|
+ * until the map is initialized in initSignatureMap.
|
|
+ * This has the effect of avoiding the signature
|
|
+ * work for the first call of getPublicMethods().
|
|
+ */
|
|
+ if (sigs.isEmpty()) {
|
|
+ m.add(method);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Avoid adding duplicate accessible methods on
|
|
+ * the list.
|
|
+ */
|
|
+ String signature = getSignature(method);
|
|
+ if (!sigs.containsKey(signature)) {
|
|
+ m.add(method);
|
|
+ sigs.put(signature, method);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Return a canonical method signature for the method.
|
|
+ * We care only about the simple method name and the
|
|
+ * the number, type and order of the parameters.
|
|
+ * Exception declarations are not part of a method
|
|
+ * signature nor is the return type.
|
|
+ */
|
|
+ private static String getSignature(Method method) {
|
|
+ StringBuffer sb = new StringBuffer();
|
|
+
|
|
+ sb.append(method.getName());
|
|
+ Class[] params = method.getParameterTypes();
|
|
+ sb.append('(');
|
|
+ if (params.length > 0) {
|
|
+ sb.append(params[0].getName());
|
|
+ }
|
|
+ for (int i=1; i < params.length; i++) {
|
|
+ sb.append(',');
|
|
+ sb.append(params[i].getName());
|
|
+ }
|
|
+ sb.append(')');
|
|
+
|
|
+ return sb.toString();
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Discover the public fields on public classes
|
|
+ * and interfaces accessible to the calling
|
|
+ * JavaScript code.
|
|
+ */
|
|
+ public static Field[] getJScriptFields(Class cls) {
|
|
+ List m = new ArrayList(); /* the valid fields we find */
|
|
+
|
|
+ /*
|
|
+ * Temporary map of field name when we decide
|
|
+ * that a simple call to target.getFields() returns
|
|
+ * inaccessible fields and we must search for alternative
|
|
+ * supermethods that might be accessible. We can toss
|
|
+ * this when we're done searching.
|
|
+ */
|
|
+ Map names = new HashMap();
|
|
+
|
|
+ while (cls != null) {
|
|
+ boolean done = getPublicFields(cls, m, names);
|
|
+ if (done) {
|
|
+ break;
|
|
+ }
|
|
+ getJScriptInterfaceFields(cls, m, names);
|
|
+ cls = cls.getSuperclass();
|
|
+ }
|
|
+ return (Field[]) m.toArray(new Field[m.size()]);
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Process the immediate interfaces of this class or interface.
|
|
+ */
|
|
+ private static void getJScriptInterfaceFields(Class cls, List m, Map names) {
|
|
+ Class[] intfs = cls.getInterfaces();
|
|
+ for (int i=0; i < intfs.length; i++) {
|
|
+ Class intf = intfs[i];
|
|
+ boolean done = getPublicFields(intf, m, names);
|
|
+ if (!done) {
|
|
+ getJScriptInterfaceFields(intf, m, names);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ *
|
|
+ * Process the fields in this class or interface
|
|
+ */
|
|
+ private static boolean getPublicFields(Class cls, List m, Map names) {
|
|
+ Field[] fields = null;
|
|
+ try {
|
|
+
|
|
+ /*
|
|
+ * This class or interface is non-public so we
|
|
+ * can't use any of it's fields. Go back and
|
|
+ * try again with a superclass or superinterface.
|
|
+ */
|
|
+ if (!Modifier.isPublic(cls.getModifiers())) {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if (!JSClassLoader.isPackageAccessible(cls)) {
|
|
+ return false;
|
|
+ }
|
|
+ fields = cls.getFields();
|
|
+ } catch (SecurityException se) {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Check for inherited fields with non-public
|
|
+ * declaring classes. They might hide
|
|
+ * fields from public classes or interfaces.
|
|
+ */
|
|
+ boolean done = true;
|
|
+ for (int i=0; i < fields.length; i++) {
|
|
+ Class dc = fields[i].getDeclaringClass();
|
|
+ if (!Modifier.isPublic(dc.getModifiers())) {
|
|
+ done = false;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ if (done) {
|
|
+ /*
|
|
+ * We're done. Spray all the fields into
|
|
+ * the list and then we're out of here.
|
|
+ */
|
|
+ for (int i=0; i < fields.length; i++) {
|
|
+ addField(m, names, fields[i]);
|
|
+ }
|
|
+ } else {
|
|
+ /*
|
|
+ * Simulate cls.getDeclaredFields() by
|
|
+ * stripping away inherited fields.
|
|
+ */
|
|
+ for (int i=0; i < fields.length; i++) {
|
|
+ Class dc = fields[i].getDeclaringClass();
|
|
+ if (cls.equals(dc)) {
|
|
+ addField(m, names, fields[i]);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return done;
|
|
+ }
|
|
+
|
|
+ private static void addField(List m, Map names, Field field) {
|
|
+ /*
|
|
+ * Avoid adding duplicate accessible fields on
|
|
+ * the list.
|
|
+ */
|
|
+ String name = field.getName();
|
|
+ if (!names.containsKey(name)) {
|
|
+ m.add(field);
|
|
+ names.put(name, field);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+
|