2003/05/12 05:31:48
[org.ibex.core.git] / src / org / mozilla / javascript / JavaMembers.java
diff --git a/src/org/mozilla/javascript/JavaMembers.java b/src/org/mozilla/javascript/JavaMembers.java
deleted file mode 100644 (file)
index fbe225c..0000000
+++ /dev/null
@@ -1,591 +0,0 @@
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
- *\r
- * The contents of this file are subject to the Netscape Public\r
- * License Version 1.1 (the "License"); you may not use this file\r
- * except in compliance with the License. You may obtain a copy of\r
- * the License at http://www.mozilla.org/NPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS\r
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
- * implied. See the License for the specific language governing\r
- * rights and limitations under the License.\r
- *\r
- * The Original Code is Rhino code, released\r
- * May 6, 1999.\r
- *\r
- * The Initial Developer of the Original Code is Netscape\r
- * Communications Corporation.  Portions created by Netscape are\r
- * Copyright (C) 1997-2000 Netscape Communications Corporation. All\r
- * Rights Reserved.\r
- *\r
- * Contributor(s): \r
- * Norris Boyd\r
- * Frank Mitchell\r
- * Mike Shaver\r
- * Kurt Westerfeld\r
- *\r
- * Alternatively, the contents of this file may be used under the\r
- * terms of the GNU Public License (the "GPL"), in which case the\r
- * provisions of the GPL are applicable instead of those above.\r
- * If you wish to allow use of your version of this file only\r
- * under the terms of the GPL and not to allow others to use your\r
- * version of this file under the NPL, indicate your decision by\r
- * deleting the provisions above and replace them with the notice\r
- * and other provisions required by the GPL.  If you do not delete\r
- * the provisions above, a recipient may use your version of this\r
- * file under either the NPL or the GPL.\r
- */\r
-\r
-package org.mozilla.javascript;\r
-\r
-import java.lang.reflect.*;\r
-import java.util.Hashtable;\r
-import java.util.Enumeration;\r
-\r
-/**\r
- *\r
- * @author Mike Shaver\r
- * @author Norris Boyd\r
- * @see NativeJavaObject\r
- * @see NativeJavaClass\r
- */\r
-class JavaMembers {\r
-\r
-    JavaMembers(Scriptable scope, Class cl) {\r
-        this.members = new Hashtable(23);\r
-        this.staticMembers = new Hashtable(7);\r
-        this.cl = cl;\r
-        reflect(scope, cl);\r
-    }\r
-\r
-    boolean has(String name, boolean isStatic) {\r
-        Hashtable ht = isStatic ? staticMembers : members;\r
-        Object obj = ht.get(name);\r
-        if (obj != null) {\r
-            return true;\r
-        } else {\r
-            Member member = this.findExplicitFunction(name, isStatic);\r
-            return member != null;\r
-        }\r
-    }\r
-\r
-    Object get(Scriptable scope, String name, Object javaObject,\r
-               boolean isStatic)\r
-    {\r
-        Hashtable ht = isStatic ? staticMembers : members;\r
-        Object member = ht.get(name);\r
-        if (!isStatic && member == null) {\r
-            // Try to get static member from instance (LC3)\r
-            member = staticMembers.get(name);\r
-        }\r
-        if (member == null) {\r
-            member = this.getExplicitFunction(scope, name, \r
-                                              javaObject, isStatic);\r
-            if (member == null)\r
-                return Scriptable.NOT_FOUND;\r
-        }\r
-        if (member instanceof Scriptable)\r
-            return member;      // why is this here?\r
-        Object rval;\r
-        Class type;\r
-        try {\r
-            if (member instanceof BeanProperty) {\r
-                BeanProperty bp = (BeanProperty) member;\r
-                rval = bp.getter.invoke(javaObject, ScriptRuntime.emptyArgs);\r
-                type = bp.getter.getReturnType();\r
-            } else {\r
-                Field field = (Field) member;\r
-                rval = field.get(isStatic ? null : javaObject);\r
-                type = field.getType();\r
-            }\r
-        } catch (IllegalAccessException accEx) {\r
-            throw new RuntimeException("unexpected IllegalAccessException "+\r
-                                       "accessing Java field");\r
-        } catch (InvocationTargetException e) {\r
-            throw WrappedException.wrapException(\r
-                JavaScriptException.wrapException(scope, e));\r
-        }\r
-        // Need to wrap the object before we return it.\r
-        scope = ScriptableObject.getTopLevelScope(scope);\r
-        return NativeJavaObject.wrap(scope, rval, type);\r
-    }\r
-\r
-    Member findExplicitFunction(String name, boolean isStatic) {\r
-        Hashtable ht = isStatic ? staticMembers : members;\r
-        int sigStart = name.indexOf('(');\r
-        Member[] methodsOrCtors = null;\r
-        NativeJavaMethod method = null;\r
-        boolean isCtor = (isStatic && sigStart == 0);\r
-\r
-        if (isCtor) {\r
-            // Explicit request for an overloaded constructor\r
-            methodsOrCtors = ctors;\r
-        }\r
-        else if (sigStart > 0) {\r
-            // Explicit request for an overloaded method\r
-            String trueName = name.substring(0,sigStart);\r
-            Object obj = ht.get(trueName);\r
-            if (!isStatic && obj == null) {\r
-                // Try to get static member from instance (LC3)\r
-                obj = staticMembers.get(trueName);\r
-            }\r
-            if (obj != null && obj instanceof NativeJavaMethod) {\r
-                method = (NativeJavaMethod)obj;\r
-                methodsOrCtors = method.getMethods();\r
-            }\r
-        }\r
-\r
-        if (methodsOrCtors != null) {\r
-            for (int i = 0; i < methodsOrCtors.length; i++) {\r
-                String nameWithSig = \r
-                    NativeJavaMethod.signature(methodsOrCtors[i]);\r
-                if (name.equals(nameWithSig)) {\r
-                    return methodsOrCtors[i];\r
-                }\r
-            }\r
-        }\r
-\r
-        return null;\r
-    }\r
-\r
-    Object getExplicitFunction(Scriptable scope, String name, \r
-                               Object javaObject, boolean isStatic) \r
-    {\r
-        Hashtable ht = isStatic ? staticMembers : members;\r
-        Object member = null;\r
-        Member methodOrCtor = this.findExplicitFunction(name, isStatic);\r
-\r
-        if (methodOrCtor != null) {\r
-            Scriptable prototype = \r
-                ScriptableObject.getFunctionPrototype(scope);\r
-\r
-            if (methodOrCtor instanceof Constructor) {\r
-                NativeJavaConstructor fun = \r
-                    new NativeJavaConstructor((Constructor)methodOrCtor);\r
-                fun.setPrototype(prototype);\r
-                member = fun;\r
-                ht.put(name, fun);\r
-            } else {\r
-                String trueName = methodOrCtor.getName();\r
-                member = ht.get(trueName);\r
-\r
-                if (member instanceof NativeJavaMethod &&\r
-                    ((NativeJavaMethod)member).getMethods().length > 1 ) {\r
-                    NativeJavaMethod fun = \r
-                        new NativeJavaMethod((Method)methodOrCtor, name);\r
-                    fun.setPrototype(prototype);\r
-                    ht.put(name, fun);\r
-                    member = fun;\r
-                }\r
-            }\r
-        }\r
-\r
-        return member;\r
-    }\r
-\r
-\r
-    public void put(Scriptable scope, String name, Object javaObject, \r
-                    Object value, boolean isStatic)\r
-    {\r
-        Hashtable ht = isStatic ? staticMembers : members;\r
-        Object member = ht.get(name);\r
-        if (!isStatic && member == null) {\r
-            // Try to get static member from instance (LC3)\r
-            member = staticMembers.get(name);\r
-        }\r
-        if (member == null)\r
-            throw reportMemberNotFound(name);\r
-        if (member instanceof FieldAndMethods) {\r
-            FieldAndMethods fam = (FieldAndMethods) ht.get(name);\r
-            member = fam.getField();\r
-        }\r
-        \r
-        // Is this a bean property "set"?\r
-        if (member instanceof BeanProperty) { \r
-            try {\r
-                Method method = ((BeanProperty) member).setter;\r
-                if (method == null)\r
-                    throw reportMemberNotFound(name);\r
-                Class[] types = method.getParameterTypes();\r
-                Object[] params = { NativeJavaObject.coerceType(types[0], value) };\r
-                method.invoke(javaObject, params);\r
-            } catch (IllegalAccessException accessEx) {\r
-                throw new RuntimeException("unexpected IllegalAccessException " +\r
-                                           "accessing Java field");\r
-            } catch (InvocationTargetException e) {\r
-                throw WrappedException.wrapException(\r
-                    JavaScriptException.wrapException(scope, e));\r
-            }\r
-        }\r
-        else {\r
-            Field field = null;\r
-            try {\r
-                field = (Field) member;\r
-                if (field == null) {\r
-                    throw Context.reportRuntimeError1(\r
-                        "msg.java.internal.private", name);\r
-                }\r
-                field.set(javaObject,\r
-                          NativeJavaObject.coerceType(field.getType(), value));\r
-            } catch (ClassCastException e) {\r
-                throw Context.reportRuntimeError1(\r
-                    "msg.java.method.assign", name);\r
-            } catch (IllegalAccessException accessEx) {\r
-                throw new RuntimeException("unexpected IllegalAccessException "+\r
-                                           "accessing Java field");\r
-            } catch (IllegalArgumentException argEx) {\r
-                throw Context.reportRuntimeError3(\r
-                    "msg.java.internal.field.type", \r
-                    value.getClass().getName(), field,\r
-                    javaObject.getClass().getName());\r
-            }\r
-        }\r
-    }\r
-\r
-    Object[] getIds(boolean isStatic) {\r
-        Hashtable ht = isStatic ? staticMembers : members;\r
-        int len = ht.size();\r
-        Object[] result = new Object[len];\r
-        Enumeration keys = ht.keys();\r
-        for (int i=0; i < len; i++)\r
-            result[i] = keys.nextElement();\r
-        return result;\r
-    }\r
-    \r
-    Class getReflectedClass() {\r
-        return cl;\r
-    }\r
-    \r
-    void reflectField(Scriptable scope, Field field) {\r
-        int mods = field.getModifiers();\r
-        if (!Modifier.isPublic(mods))\r
-            return;\r
-        boolean isStatic = Modifier.isStatic(mods);\r
-        Hashtable ht = isStatic ? staticMembers : members;\r
-        String name = field.getName();\r
-        Object member = ht.get(name);\r
-        if (member != null) {\r
-            if (member instanceof NativeJavaMethod) {\r
-                NativeJavaMethod method = (NativeJavaMethod) member;\r
-                FieldAndMethods fam = new FieldAndMethods(method.getMethods(),\r
-                                                          field,\r
-                                                          null);\r
-                fam.setPrototype(ScriptableObject.getFunctionPrototype(scope));\r
-                getFieldAndMethodsTable(isStatic).put(name, fam);\r
-                ht.put(name, fam);\r
-                return;\r
-            }\r
-            if (member instanceof Field) {\r
-               Field oldField = (Field) member;\r
-               // If this newly reflected field shadows an inherited field, \r
-                // then replace it. Otherwise, since access to the field \r
-                // would be ambiguous from Java, no field should be reflected.\r
-               // For now, the first field found wins, unless another field \r
-                // explicitly shadows it.\r
-               if (oldField.getDeclaringClass().isAssignableFrom(field.getDeclaringClass()))\r
-                       ht.put(name, field);\r
-               return;\r
-            }\r
-            throw new RuntimeException("unknown member type");\r
-        }\r
-        ht.put(name, field);\r
-    }\r
-\r
-    void reflectMethod(Scriptable scope, Method method) {\r
-        int mods = method.getModifiers();\r
-        if (!Modifier.isPublic(mods))\r
-            return;\r
-        boolean isStatic = Modifier.isStatic(mods);\r
-        Hashtable ht = isStatic ? staticMembers : members;\r
-        String name = method.getName();\r
-        NativeJavaMethod fun = (NativeJavaMethod) ht.get(name);\r
-        if (fun == null) {\r
-            fun = new NativeJavaMethod();\r
-            if (scope != null)\r
-                fun.setPrototype(ScriptableObject.getFunctionPrototype(scope));\r
-            ht.put(name, fun);\r
-            fun.add(method);\r
-        } else {\r
-            fun.add(method);\r
-        }\r
-    }\r
-\r
-    void reflect(Scriptable scope, Class cl) {\r
-        // We reflect methods first, because we want overloaded field/method\r
-        // names to be allocated to the NativeJavaMethod before the field\r
-        // gets in the way.\r
-        Method[] methods = cl.getMethods();\r
-        for (int i = 0; i < methods.length; i++)\r
-            reflectMethod(scope, methods[i]);\r
-        \r
-        Field[] fields = cl.getFields();\r
-        for (int i = 0; i < fields.length; i++)\r
-            reflectField(scope, fields[i]);\r
-\r
-        makeBeanProperties(scope, false);\r
-        makeBeanProperties(scope, true);\r
-        \r
-        ctors = cl.getConstructors();\r
-    }\r
-    \r
-    Hashtable getFieldAndMethodsTable(boolean isStatic) {\r
-        Hashtable fmht = isStatic ? staticFieldAndMethods\r
-                                  : fieldAndMethods;\r
-        if (fmht == null) {\r
-            fmht = new Hashtable(11);\r
-            if (isStatic)\r
-                staticFieldAndMethods = fmht;\r
-            else\r
-                fieldAndMethods = fmht;\r
-        }\r
-        \r
-        return fmht;\r
-    }\r
-\r
-    void makeBeanProperties(Scriptable scope, boolean isStatic) {\r
-        Hashtable ht = isStatic ? staticMembers : members;\r
-        Hashtable toAdd = new Hashtable();\r
-        \r
-        // Now, For each member, make "bean" properties.\r
-        for (Enumeration e = ht.keys(); e.hasMoreElements(); ) {\r
-            \r
-            // Is this a getter?\r
-            String name = (String) e.nextElement();\r
-            boolean memberIsGetMethod = name.startsWith("get");\r
-            boolean memberIsIsMethod = name.startsWith("is");\r
-            if (memberIsGetMethod || memberIsIsMethod) {\r
-                // Double check name component.\r
-                String nameComponent = name.substring(memberIsGetMethod ? 3 : 2);\r
-                if (nameComponent.length() == 0) \r
-                    continue;\r
-                \r
-                // Make the bean property name.\r
-                String beanPropertyName = nameComponent;\r
-                if (Character.isUpperCase(nameComponent.charAt(0))) {\r
-                    if (nameComponent.length() == 1) {\r
-                        beanPropertyName = nameComponent.substring(0, 1).toLowerCase();\r
-                    } else if (!Character.isUpperCase(nameComponent.charAt(1))) {\r
-                        beanPropertyName = Character.toLowerCase(nameComponent.charAt(0)) + \r
-                                           nameComponent.substring(1);\r
-                    }\r
-                }\r
-                \r
-                // If we already have a member by this name, don't do this\r
-                // property.\r
-                if (ht.containsKey(beanPropertyName))\r
-                    continue;\r
-                \r
-                // Get the method by this name.\r
-                Object method = ht.get(name);\r
-                if (!(method instanceof NativeJavaMethod))\r
-                    continue;\r
-                NativeJavaMethod getJavaMethod = (NativeJavaMethod) method;\r
-                \r
-                // Grab and inspect the getter method; does it have an empty parameter list,\r
-                // with a return value (eg. a getSomething() or isSomething())?\r
-                Class[] params;\r
-                Method[] getMethods = getJavaMethod.getMethods();\r
-                Class type;\r
-                if (getMethods != null && \r
-                    getMethods.length == 1 && \r
-                    (type = getMethods[0].getReturnType()) != null &&\r
-                    (params = getMethods[0].getParameterTypes()) != null && \r
-                    params.length == 0) \r
-                { \r
-                    \r
-                    // Make sure the method static-ness is preserved for this property.\r
-                    if (isStatic && !Modifier.isStatic(getMethods[0].getModifiers()))\r
-                        continue;\r
-                        \r
-                    // We have a getter.  Now, do we have a setter?\r
-                    Method setMethod = null;\r
-                    String setter = "set" + nameComponent;\r
-                    if (ht.containsKey(setter)) { \r
-\r
-                        // Is this value a method?\r
-                        method = ht.get(setter);\r
-                        if (method instanceof NativeJavaMethod) {\r
-                        \r
-                            //\r
-                            // Note: it may be preferable to allow NativeJavaMethod.findFunction()\r
-                            //       to find the appropriate setter; unfortunately, it requires an\r
-                            //       instance of the target arg to determine that.\r
-                            //\r
-\r
-                            // Make two passes: one to find a method with direct type assignment, \r
-                            // and one to find a widening conversion.\r
-                            NativeJavaMethod setJavaMethod = (NativeJavaMethod) method;\r
-                            Method[] setMethods = setJavaMethod.getMethods();\r
-                            for (int pass = 1; pass <= 2 && setMethod == null; ++pass) {\r
-                                for (int i = 0; i < setMethods.length; ++i) {\r
-                                    if (setMethods[i].getReturnType() == void.class &&\r
-                                        (!isStatic || Modifier.isStatic(setMethods[i].getModifiers())) &&\r
-                                        (params = setMethods[i].getParameterTypes()) != null && \r
-                                        params.length == 1 ) { \r
-                                        \r
-                                        if ((pass == 1 && params[0] == type) ||\r
-                                            (pass == 2 && params[0].isAssignableFrom(type))) { \r
-                                            setMethod = setMethods[i];\r
-                                            break;\r
-                                        }\r
-                                    }\r
-                                }\r
-                            }\r
-                        }\r
-                    }\r
-                            \r
-                    // Make the property.\r
-                    BeanProperty bp = new BeanProperty(getMethods[0], setMethod);\r
-                    toAdd.put(beanPropertyName, bp);\r
-                }\r
-            }\r
-        }           \r
-        \r
-        // Add the new bean properties.\r
-        for (Enumeration e = toAdd.keys(); e.hasMoreElements();) {\r
-            String key = (String) e.nextElement();\r
-            Object value = toAdd.get(key);\r
-            ht.put(key, value);\r
-        }\r
-    }\r
-\r
-    Hashtable getFieldAndMethodsObjects(Scriptable scope, Object javaObject,\r
-                                        boolean isStatic) \r
-    {\r
-        Hashtable ht = isStatic ? staticFieldAndMethods : fieldAndMethods;\r
-        if (ht == null)\r
-            return null;\r
-        int len = ht.size();\r
-        Hashtable result = new Hashtable(Math.max(len,1));\r
-        Enumeration e = ht.elements();\r
-        while (len-- > 0) {\r
-            FieldAndMethods fam = (FieldAndMethods) e.nextElement();\r
-            fam = (FieldAndMethods) fam.clone();\r
-            fam.setJavaObject(javaObject);\r
-            result.put(fam.getName(), fam);\r
-        }\r
-        return result;\r
-    }\r
-\r
-    Constructor[] getConstructors() {\r
-        return ctors;\r
-    }\r
-\r
-    static JavaMembers lookupClass(Scriptable scope, Class dynamicType,\r
-                                   Class staticType)\r
-    {\r
-        Class cl = dynamicType;\r
-        Hashtable ct = classTable;  // use local reference to avoid synchronize\r
-        JavaMembers members = (JavaMembers) ct.get(cl);\r
-        if (members != null)\r
-            return members;\r
-        if (staticType != null && staticType != dynamicType &&\r
-            !Modifier.isPublic(dynamicType.getModifiers()) &&\r
-            Modifier.isPublic(staticType.getModifiers()))\r
-        {\r
-            cl = staticType;\r
-            \r
-            // We can use the static type, and that is OK, but we'll trace\r
-            // back the java class chain here to look for something more suitable.\r
-            for (Class parentType = dynamicType; \r
-                 parentType != null && parentType != ScriptRuntime.ObjectClass;\r
-                 parentType = parentType.getSuperclass())\r
-            {\r
-                if (Modifier.isPublic(parentType.getModifiers())) {\r
-                   cl = parentType;\r
-                   break;\r
-                }\r
-            }\r
-        }\r
-        try {\r
-            members = new JavaMembers(scope, cl);\r
-        } catch (SecurityException e) {\r
-            // Reflection may fail for objects that are in a restricted \r
-            // access package (e.g. sun.*).  If we get a security\r
-            // exception, try again with the static type. Otherwise, \r
-            // rethrow the exception.\r
-            if (cl != staticType)\r
-                members = new JavaMembers(scope, staticType);\r
-            else\r
-                throw e;\r
-        }\r
-        if (Context.isCachingEnabled) \r
-            ct.put(cl, members);\r
-        return members;\r
-    }\r
-\r
-    RuntimeException reportMemberNotFound(String memberName) {\r
-        return Context.reportRuntimeError2(\r
-            "msg.java.member.not.found", cl.getName(), memberName);\r
-    }\r
-\r
-    static Hashtable classTable = new Hashtable();\r
-\r
-    private Class cl;\r
-    private Hashtable members;\r
-    private Hashtable fieldAndMethods;\r
-    private Hashtable staticMembers;\r
-    private Hashtable staticFieldAndMethods;\r
-    private Constructor[] ctors;\r
-}\r
-\r
-class BeanProperty {\r
-    BeanProperty(Method getter, Method setter) {\r
-        this.getter = getter;\r
-        this.setter = setter;\r
-    }\r
-    Method getter;\r
-    Method setter;\r
-}\r
-\r
-class FieldAndMethods extends NativeJavaMethod {\r
-\r
-    FieldAndMethods(Method[] methods, Field field, String name) {\r
-        super(methods);\r
-        this.field = field;\r
-        this.name = name;\r
-    }\r
-\r
-    void setJavaObject(Object javaObject) {\r
-        this.javaObject = javaObject;\r
-    }\r
-\r
-    String getName() {\r
-        if (field == null)\r
-            return name;\r
-        return field.getName();\r
-    }\r
-\r
-    Field getField() {\r
-        return field;\r
-    }\r
-    \r
-    public Object getDefaultValue(Class hint) {\r
-        if (hint == ScriptRuntime.FunctionClass)\r
-            return this;\r
-        Object rval;\r
-        Class type;\r
-        try {\r
-            rval = field.get(javaObject);\r
-            type = field.getType();\r
-        } catch (IllegalAccessException accEx) {\r
-            throw Context.reportRuntimeError1(\r
-                "msg.java.internal.private", getName());\r
-        }\r
-        rval = NativeJavaObject.wrap(this, rval, type);\r
-        if (rval instanceof Scriptable) {\r
-            rval = ((Scriptable) rval).getDefaultValue(hint);\r
-        }\r
-        return rval;\r
-    }\r
-\r
-    public Object clone() {\r
-        FieldAndMethods result = new FieldAndMethods(methods, field, name);\r
-        result.javaObject = javaObject;\r
-        return result;\r
-    }\r
-    \r
-    private Field field;\r
-    private Object javaObject;\r
-    private String name;\r
-}\r