Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
   *
   * This Source Code Form is subject to the terms of the Mozilla Public
   * License, v. 2.0. If a copy of the MPL was not distributed with this
   * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  
  package org.mozilla.javascript;
  
 import java.util.*;
 
 import static java.lang.reflect.Modifier.isProtected;
 import static java.lang.reflect.Modifier.isPublic;

Author(s):
Mike Shaver
Norris Boyd
See also:
NativeJavaObject
NativeJavaClass
 
 class JavaMembers
 {
     JavaMembers(Scriptable scopeClass<?> cl)
     {
         this(scopeclfalse);
     }
 
     JavaMembers(Scriptable scopeClass<?> clboolean includeProtected)
     {
         try {
             Context cx = ContextFactory.getGlobal().enterContext();
             ClassShutter shutter = cx.getClassShutter();
             if (shutter != null && !shutter.visibleToScripts(cl.getName())) {
                 throw Context.reportRuntimeError1("msg.access.prohibited",
                                                   cl.getName());
             }
             this. = new HashMap<String,Object>();
             this. = new HashMap<String,Object>();
             this. = cl;
             boolean includePrivate = cx.hasFeature(
                     .);
             reflect(scopeincludeProtectedincludePrivate);
         } finally {
             Context.exit();
         }
     }
 
     boolean has(String nameboolean isStatic)
     {
         Map<String,Objectht = isStatic ?  : ;
         Object obj = ht.get(name);
         if (obj != null) {
             return true;
         }
         return findExplicitFunction(nameisStatic) != null;
     }
 
     Object get(Scriptable scopeString nameObject javaObject,
                boolean isStatic)
     {
         Map<String,Objectht = isStatic ?  : ;
         Object member = ht.get(name);
         if (!isStatic && member == null) {
             // Try to get static member from instance (LC3)
             member = .get(name);
         }
         if (member == null) {
             member = this.getExplicitFunction(scopename,
                                               javaObjectisStatic);
             if (member == null)
                 return .;
         }
         if (member instanceof Scriptable) {
             return member;
         }
         Context cx = Context.getContext();
         Object rval;
         Class<?> type;
         try {
             if (member instanceof BeanProperty) {
                 BeanProperty bp = (BeanPropertymember;
                 if (bp.getter == null)
                     return .;
                 rval = bp.getter.invoke(javaObject.);
                 type = bp.getter.method().getReturnType();
             } else {
                 Field field = (Fieldmember;
                 rval = field.get(isStatic ? null : javaObject);
                 type = field.getType();
             }
         } catch (Exception ex) {
             throw Context.throwAsScriptRuntimeEx(ex);
         }
         // Need to wrap the object before we return it.
         scope = ScriptableObject.getTopLevelScope(scope);
         return cx.getWrapFactory().wrap(cxscopervaltype);
     }
 
    void put(Scriptable scopeString nameObject javaObject,
             Object valueboolean isStatic)
    {
        Map<String,Objectht = isStatic ?  : ;
        Object member = ht.get(name);
        if (!isStatic && member == null) {
            // Try to get static member from instance (LC3)
            member = .get(name);
        }
        if (member == null)
            throw reportMemberNotFound(name);
        if (member instanceof FieldAndMethods) {
            FieldAndMethods fam = (FieldAndMethodsht.get(name);
            member = fam.field;
        }
        // Is this a bean property "set"?
        if (member instanceof BeanProperty) {
            BeanProperty bp = (BeanProperty)member;
            if (bp.setter == null) {
                throw reportMemberNotFound(name);
            }
            // If there's only one setter or if the value is null, use the
            // main setter. Otherwise, let the NativeJavaMethod decide which
            // setter to use:
            if (bp.setters == null || value == null) {
                Class<?> setType = bp.setter.argTypes[0];
                Object[] args = { Context.jsToJava(valuesetType) };
                try {
                    bp.setter.invoke(javaObjectargs);
                } catch (Exception ex) {
                  throw Context.throwAsScriptRuntimeEx(ex);
                }
            } else {
                Object[] args = { value };
                bp.setters.call(Context.getContext(),
                                ScriptableObject.getTopLevelScope(scope),
                                scopeargs);
            }
        }
        else {
            if (!(member instanceof Field)) {
                String str = (member == null) ? "msg.java.internal.private"
                                              : "msg.java.method.assign";
                throw Context.reportRuntimeError1(strname);
            }
            Field field = (Field)member;
            Object javaValue = Context.jsToJava(valuefield.getType());
            try {
                field.set(javaObjectjavaValue);
            } catch (IllegalAccessException accessEx) {
                if ((field.getModifiers() & .) != 0) {
                    // treat Java final the same as JavaScript [[READONLY]]
                    return;
                }
                throw Context.throwAsScriptRuntimeEx(accessEx);
            } catch (IllegalArgumentException argEx) {
                throw Context.reportRuntimeError3(
                    "msg.java.internal.field.type",
                    value.getClass().getName(), field,
                    javaObject.getClass().getName());
            }
        }
    }
    Object[] getIds(boolean isStatic)
    {
        Map<String,Objectmap = isStatic ?  : ;
        return map.keySet().toArray(new Object[map.size()]);
    }
    static String javaSignature(Class<?> type)
    {
        if (!type.isArray()) {
            return type.getName();
        } else {
            int arrayDimension = 0;
            do {
                ++arrayDimension;
                type = type.getComponentType();
            } while (type.isArray());
            String name = type.getName();
            String suffix = "[]";
            if (arrayDimension == 1) {
                return name.concat(suffix);
            } else {
                int length = name.length() + arrayDimension * suffix.length();
                StringBuilder sb = new StringBuilder(length);
                sb.append(name);
                while (arrayDimension != 0) {
                    --arrayDimension;
                    sb.append(suffix);
                }
                return sb.toString();
            }
        }
    }
    static String liveConnectSignature(Class<?>[] argTypes)
    {
        int N = argTypes.length;
        if (N == 0) { return "()"; }
        StringBuilder sb = new StringBuilder();
        sb.append('(');
        for (int i = 0; i != N; ++i) {
            if (i != 0) {
                sb.append(',');
            }
            sb.append(javaSignature(argTypes[i]));
        }
        sb.append(')');
        return sb.toString();
    }
    private MemberBox findExplicitFunction(String nameboolean isStatic)
    {
        int sigStart = name.indexOf('(');
        if (sigStart < 0) { return null; }
        Map<String,Objectht = isStatic ?  : ;
        MemberBox[] methodsOrCtors = null;
        boolean isCtor = (isStatic && sigStart == 0);
        if (isCtor) {
            // Explicit request for an overloaded constructor
            methodsOrCtors = .;
        } else {
            // Explicit request for an overloaded method
            String trueName = name.substring(0,sigStart);
            Object obj = ht.get(trueName);
            if (!isStatic && obj == null) {
                // Try to get static member from instance (LC3)
                obj = .get(trueName);
            }
            if (obj instanceof NativeJavaMethod) {
                NativeJavaMethod njm = (NativeJavaMethod)obj;
                methodsOrCtors = njm.methods;
            }
        }
        if (methodsOrCtors != null) {
            for (MemberBox methodsOrCtor : methodsOrCtors) {
                Class<?>[] type = methodsOrCtor.argTypes;
                String sig = liveConnectSignature(type);
                if (sigStart + sig.length() == name.length()
                        && name.regionMatches(sigStartsig, 0, sig.length()))
                {
                    return methodsOrCtor;
                }
            }
        }
        return null;
    }
    private Object getExplicitFunction(Scriptable scopeString name,
                                       Object javaObjectboolean isStatic)
    {
        Map<String,Objectht = isStatic ?  : ;
        Object member = null;
        MemberBox methodOrCtor = findExplicitFunction(nameisStatic);
        if (methodOrCtor != null) {
            Scriptable prototype =
                ScriptableObject.getFunctionPrototype(scope);
            if (methodOrCtor.isCtor()) {
                NativeJavaConstructor fun =
                    new NativeJavaConstructor(methodOrCtor);
                fun.setPrototype(prototype);
                member = fun;
                ht.put(namefun);
            } else {
                String trueName = methodOrCtor.getName();
                member = ht.get(trueName);
                if (member instanceof NativeJavaMethod &&
                    ((NativeJavaMethod)member)..length > 1 ) {
                    NativeJavaMethod fun =
                        new NativeJavaMethod(methodOrCtorname);
                    fun.setPrototype(prototype);
                    ht.put(namefun);
                    member = fun;
                }
            }
        }
        return member;
    }

    
Retrieves mapping of methods to accessible methods for a class. In case the class is not public, retrieves methods with same signature as its public methods from public superclasses and interfaces (if they exist). Basically upcasts every method to the nearest accessible method.
    private static Method[] discoverAccessibleMethods(Class<?> clazz,
                                                      boolean includeProtected,
                                                      boolean includePrivate)
    {
        Map<MethodSignature,Methodmap = new HashMap<MethodSignature,Method>();
        discoverAccessibleMethods(clazzmapincludeProtectedincludePrivate);
        return map.values().toArray(new Method[map.size()]);
    }
    private static void discoverAccessibleMethods(Class<?> clazz,
            Map<MethodSignature,Methodmapboolean includeProtected,
            boolean includePrivate)
    {
        if (isPublic(clazz.getModifiers()) || includePrivate) {
            try {
                if (includeProtected || includePrivate) {
                    while (clazz != null) {
                        try {
                            Method[] methods = clazz.getDeclaredMethods();
                            for (Method method : methods) {
                                int mods = method.getModifiers();
                                if (isPublic(mods)
                                        || isProtected(mods)
                                        || includePrivate) {
                                    MethodSignature sig = new MethodSignature(method);
                                    if (!map.containsKey(sig)) {
                                        if (includePrivate && !method.isAccessible())
                                            method.setAccessible(true);
                                        map.put(sigmethod);
                                    }
                                }
                            }
                            clazz = clazz.getSuperclass();
                        } catch (SecurityException e) {
                            // Some security settings (i.e., applets) disallow
                            // access to Class.getDeclaredMethods. Fall back to
                            // Class.getMethods.
                            Method[] methods = clazz.getMethods();
                            for (Method method : methods) {
                                MethodSignature sig = new MethodSignature(method);
                                if (!map.containsKey(sig))
                                    map.put(sigmethod);
                            }
                            break// getMethods gets superclass methods, no
                                   // need to loop any more
                        }
                    }
                } else {
                    Method[] methods = clazz.getMethods();
                    for (Method method : methods) {
                        MethodSignature sig = new MethodSignature(method);
                        // Array may contain methods with same signature but different return value!
                        if (!map.containsKey(sig))
                            map.put(sigmethod);
                    }
                }
                return;
            } catch (SecurityException e) {
                Context.reportWarning(
                        "Could not discover accessible methods of class " +
                            clazz.getName() + " due to lack of privileges, " +
                            "attemping superclasses/interfaces.");
                // Fall through and attempt to discover superclass/interface
                // methods
            }
        }
        Class<?>[] interfaces = clazz.getInterfaces();
        for (Class<?> intface : interfaces) {
            discoverAccessibleMethods(intfacemapincludeProtected,
                    includePrivate);
        }
        Class<?> superclass = clazz.getSuperclass();
        if (superclass != null) {
            discoverAccessibleMethods(superclassmapincludeProtected,
                    includePrivate);
        }
    }
    private static final class MethodSignature
    {
        private final String name;
        private final Class<?>[] args;
        private MethodSignature(String nameClass<?>[] args)
        {
            this. = name;
            this. = args;
        }
        MethodSignature(Method method)
        {
            this(method.getName(), method.getParameterTypes());
        }
        @Override
        public boolean equals(Object o)
        {
            if(o instanceof MethodSignature)
            {
                MethodSignature ms = (MethodSignature)o;
                return ms.name.equals() && Arrays.equals(ms.args);
            }
            return false;
        }
        @Override
        public int hashCode()
        {
            return .hashCode() ^ .;
        }
    }
    private void reflect(Scriptable scope,
                         boolean includeProtected,
                         boolean includePrivate)
    {
        // We reflect methods first, because we want overloaded field/method
        // names to be allocated to the NativeJavaMethod before the field
        // gets in the way.
        Method[] methods = discoverAccessibleMethods(includeProtected,
                                                     includePrivate);
        for (Method method : methods) {
            int mods = method.getModifiers();
            boolean isStatic = Modifier.isStatic(mods);
            Map<String,Objectht = isStatic ?  : ;
            String name = method.getName();
            Object value = ht.get(name);
            if (value == null) {
                ht.put(namemethod);
            } else {
                ObjArray overloadedMethods;
                if (value instanceof ObjArray) {
                    overloadedMethods = (ObjArray)value;
                } else {
                    if (!(value instanceof Method)) Kit.codeBug();
                    // value should be instance of Method as at this stage
                    // staticMembers and members can only contain methods
                    overloadedMethods = new ObjArray();
                    overloadedMethods.add(value);
                    ht.put(nameoverloadedMethods);
                }
                overloadedMethods.add(method);
            }
        }
        // replace Method instances by wrapped NativeJavaMethod objects
        // first in staticMembers and then in members
        for (int tableCursor = 0; tableCursor != 2; ++tableCursor) {
            boolean isStatic = (tableCursor == 0);
            Map<String,Objectht = isStatic ?  : ;
            for (Map.Entry<StringObjectentryht.entrySet()) {
                MemberBox[] methodBoxes;
                Object value = entry.getValue();
                if (value instanceof Method) {
                    methodBoxes = new MemberBox[1];
                    methodBoxes[0] = new MemberBox((Method)value);
                } else {
                    ObjArray overloadedMethods = (ObjArray)value;
                    int N = overloadedMethods.size();
                    if (N < 2) Kit.codeBug();
                    methodBoxes = new MemberBox[N];
                    for (int i = 0; i != N; ++i) {
                        Method method = (Method)overloadedMethods.get(i);
                        methodBoxes[i] = new MemberBox(method);
                    }
                }
                NativeJavaMethod fun = new NativeJavaMethod(methodBoxes);
                if (scope != null) {
                    ScriptRuntime.setFunctionProtoAndParent(funscope);
                }
                ht.put(entry.getKey(), fun);
            }
        }
        // Reflect fields.
        Field[] fields = getAccessibleFields(includeProtectedincludePrivate);
        for (Field field : fields) {
            String name = field.getName();
            int mods = field.getModifiers();
            try {
                boolean isStatic = Modifier.isStatic(mods);
                Map<String,Objectht = isStatic ?  : ;
                Object member = ht.get(name);
                if (member == null) {
                    ht.put(namefield);
                } else if (member instanceof NativeJavaMethod) {
                    NativeJavaMethod method = (NativeJavaMethodmember;
                    FieldAndMethods fam
                        = new FieldAndMethods(scopemethod.methodsfield);
                    Map<String,FieldAndMethodsfmht = isStatic ? 
                                              : ;
                    if (fmht == null) {
                        fmht = new HashMap<String,FieldAndMethods>();
                        if (isStatic) {
                             = fmht;
                        } else {
                             = fmht;
                        }
                    }
                    fmht.put(namefam);
                    ht.put(namefam);
                } else if (member instanceof Field) {
                    Field oldField = (Fieldmember;
                    // If this newly reflected field shadows an inherited field,
                    // then replace it. Otherwise, since access to the field
                    // would be ambiguous from Java, no field should be
                    // reflected.
                    // For now, the first field found wins, unless another field
                    // explicitly shadows it.
                    if (oldField.getDeclaringClass().
                            isAssignableFrom(field.getDeclaringClass()))
                    {
                        ht.put(namefield);
                    }
                } else {
                    // "unknown member type"
                    Kit.codeBug();
                }
            } catch (SecurityException e) {
                // skip this field
                Context.reportWarning("Could not access field "
                        + name + " of class " + .getName() +
                        " due to lack of privileges.");
            }
        }
        // Create bean properties from corresponding get/set methods first for
        // static members and then for instance members
        for (int tableCursor = 0; tableCursor != 2; ++tableCursor) {
            boolean isStatic = (tableCursor == 0);
            Map<String,Objectht = isStatic ?  : ;
            Map<String,BeanPropertytoAdd = new HashMap<String,BeanProperty>();
            // Now, For each member, make "bean" properties.
            for (String nameht.keySet()) {
                // Is this a getter?
                boolean memberIsGetMethod = name.startsWith("get");
                boolean memberIsSetMethod = name.startsWith("set");
                boolean memberIsIsMethod = name.startsWith("is");
                if (memberIsGetMethod || memberIsIsMethod
                        || memberIsSetMethod) {
                    // Double check name component.
                    String nameComponent
                        = name.substring(memberIsIsMethod ? 2 : 3);
                    if (nameComponent.length() == 0)
                        continue;
                    // Make the bean property name.
                    String beanPropertyName = nameComponent;
                    char ch0 = nameComponent.charAt(0);
                    if (Character.isUpperCase(ch0)) {
                        if (nameComponent.length() == 1) {
                            beanPropertyName = nameComponent.toLowerCase();
                        } else {
                            char ch1 = nameComponent.charAt(1);
                            if (!Character.isUpperCase(ch1)) {
                                beanPropertyName = Character.toLowerCase(ch0)
                                                   +nameComponent.substring(1);
                            }
                        }
                    }
                    // If we already have a member by this name, don't do this
                    // property.
                    if (toAdd.containsKey(beanPropertyName))
                        continue;
                    Object v = ht.get(beanPropertyName);
                    if (v != null) {
                        // A private field shouldn't mask a public getter/setter
                        if (!includePrivate || !(v instanceof Member) ||
                            !Modifier.isPrivate(((Member)v).getModifiers()))
                        {
                            continue;
                        }
                    }
                    // Find the getter method, or if there is none, the is-
                    // method.
                    MemberBox getter = null;
                    getter = findGetter(isStaticht"get"nameComponent);
                    // If there was no valid getter, check for an is- method.
                    if (getter == null) {
                        getter = findGetter(isStaticht"is"nameComponent);
                    }
                    // setter
                    MemberBox setter = null;
                    NativeJavaMethod setters = null;
                    String setterName = "set".concat(nameComponent);
                    if (ht.containsKey(setterName)) {
                        // Is this value a method?
                        Object member = ht.get(setterName);
                        if (member instanceof NativeJavaMethod) {
                            NativeJavaMethod njmSet = (NativeJavaMethod)member;
                            if (getter != null) {
                                // We have a getter. Now, do we have a matching
                                // setter?
                                Class<?> type = getter.method().getReturnType();
                                setter = extractSetMethod(typenjmSet.methods,
                                                            isStatic);
                            } else {
                                // No getter, find any set method
                                setter = extractSetMethod(njmSet.methods,
                                                            isStatic);
                            }
                            if (njmSet.methods.length > 1) {
                                setters = njmSet;
                            }
                        }
                    }
                    // Make the property.
                    BeanProperty bp = new BeanProperty(gettersetter,
                                                       setters);
                    toAdd.put(beanPropertyNamebp);
                }
            }
            // Add the new bean properties.
            for (String keytoAdd.keySet()) {
                Object value = toAdd.get(key);
                ht.put(keyvalue);
            }
        }
        // Reflect constructors
        Constructor<?>[] constructors = getAccessibleConstructors(includePrivate);
        MemberBox[] ctorMembers = new MemberBox[constructors.length];
        for (int i = 0; i != constructors.length; ++i) {
            ctorMembers[i] = new MemberBox(constructors[i]);
        }
         = new NativeJavaMethod(ctorMembers.getSimpleName());
    }
    private Constructor<?>[] getAccessibleConstructors(boolean includePrivate)
    {
      // The JVM currently doesn't allow changing access on java.lang.Class
      // constructors, so don't try
      if (includePrivate &&  != .) {
          try {
              Constructor<?>[] cons = .getDeclaredConstructors();
              AccessibleObject.setAccessible(construe);
              return cons;
          } catch (SecurityException e) {
              // Fall through to !includePrivate case
              Context.reportWarning("Could not access constructor " +
                    " of class " + .getName() +
                    " due to lack of privileges.");
          }
      }
      return .getConstructors();
    }
    private Field[] getAccessibleFields(boolean includeProtected,
                                        boolean includePrivate) {
        if (includePrivate || includeProtected) {
            try {
                List<FieldfieldsList = new ArrayList<Field>();
                Class<?> currentClass = ;
                while (currentClass != null) {
                    // get all declared fields in this class, make them
                    // accessible, and save
                    Field[] declared = currentClass.getDeclaredFields();
                    for (Field field : declared) {
                        int mod = field.getModifiers();
                        if (includePrivate || isPublic(mod) || isProtected(mod)) {
                            if (!field.isAccessible())
                                field.setAccessible(true);
                            fieldsList.add(field);
                        }
                    }
                    // walk up superclass chain.  no need to deal specially with
                    // interfaces, since they can't have fields
                    currentClass = currentClass.getSuperclass();
                }
                return fieldsList.toArray(new Field[fieldsList.size()]);
            } catch (SecurityException e) {
                // fall through to !includePrivate case
            }
        }
        return .getFields();
    }
    private MemberBox findGetter(boolean isStaticMap<String,ObjecthtString prefix,
                                 String propertyName)
    {
        String getterName = prefix.concat(propertyName);
        if (ht.containsKey(getterName)) {
            // Check that the getter is a method.
            Object member = ht.get(getterName);
            if (member instanceof NativeJavaMethod) {
                NativeJavaMethod njmGet = (NativeJavaMethodmember;
                return extractGetMethod(njmGet.methodsisStatic);
            }
        }
        return null;
    }
    private static MemberBox extractGetMethod(MemberBox[] methods,
                                              boolean isStatic)
    {
        // Inspect the list of all MemberBox for the only one having no
        // parameters
        for (MemberBox method : methods) {
            // Does getter method have an empty parameter list with a return
            // value (eg. a getSomething() or isSomething())?
            if (method.argTypes.length == 0 && (!isStatic || method.isStatic())) {
                Class<?> type = method.method().getReturnType();
                if (type != .) {
                    return method;
                }
                break;
            }
        }
        return null;
    }
    private static MemberBox extractSetMethod(Class<?> typeMemberBox[] methods,
                                              boolean isStatic)
    {
        //
        // Note: it may be preferable to allow NativeJavaMethod.findFunction()
        //       to find the appropriate setter; unfortunately, it requires an
        //       instance of the target arg to determine that.
        //
        // Make two passes: one to find a method with direct type assignment,
        // and one to find a widening conversion.
        for (int pass = 1; pass <= 2; ++pass) {
            for (MemberBox method : methods) {
                if (!isStatic || method.isStatic()) {
                    Class<?>[] params = method.argTypes;
                    if (params.length == 1) {
                        if (pass == 1) {
                            if (params[0] == type) {
                                return method;
                            }
                        } else {
                            if (pass != 2) Kit.codeBug();
                            if (params[0].isAssignableFrom(type)) {
                                return method;
                            }
                        }
                    }
                }
            }
        }
        return null;
    }
    private static MemberBox extractSetMethod(MemberBox[] methods,
                                              boolean isStatic)
    {
        for (MemberBox method : methods) {
            if (!isStatic || method.isStatic()) {
                if (method.method().getReturnType() == .) {
                    if (method.argTypes.length == 1) {
                        return method;
                    }
                }
            }
        }
        return null;
    }
            Object javaObjectboolean isStatic)
    {
        Map<String,FieldAndMethodsht = isStatic ?  : ;
        if (ht == null)
            return null;
        int len = ht.size();
        Map<String,FieldAndMethodsresult = new HashMap<String,FieldAndMethods>(len);
        for (FieldAndMethods famht.values()) {
            FieldAndMethods famNew = new FieldAndMethods(scopefam.methods,
                                                         fam.field);
            famNew.javaObject = javaObject;
            result.put(fam.field.getName(), famNew);
        }
        return result;
    }
    static JavaMembers lookupClass(Scriptable scopeClass<?> dynamicType,
                                   Class<?> staticTypeboolean includeProtected)
    {
        JavaMembers members;
        ClassCache cache = ClassCache.get(scope);
        Map<Class<?>,JavaMembersct = cache.getClassCacheMap();
        Class<?> cl = dynamicType;
        for (;;) {
            members = ct.get(cl);
            if (members != null) {
                if (cl != dynamicType) {
                    // member lookup for the original class failed because of
                    // missing privileges, cache the result so we don't try again
                    ct.put(dynamicTypemembers);
                }
                return members;
            }
            try {
                members = new JavaMembers(cache.getAssociatedScope(), cl,
                        includeProtected);
                break;
            } catch (SecurityException e) {
                // Reflection may fail for objects that are in a restricted
                // access package (e.g. sun.*).  If we get a security
                // exception, try again with the static type if it is interface.
                // Otherwise, try superclass
                if (staticType != null && staticType.isInterface()) {
                    cl = staticType;
                    staticType = null// try staticType only once
                } else {
                    Class<?> parent = cl.getSuperclass();
                    if (parent == null) {
                        if (cl.isInterface()) {
                            // last resort after failed staticType interface
                            parent = .;
                        } else {
                            throw e;
                        }
                    }
                    cl = parent;
                }
            }
        }
        if (cache.isCachingEnabled()) {
            ct.put(clmembers);
            if (cl != dynamicType) {
                // member lookup for the original class failed because of
                // missing privileges, cache the result so we don't try again
                ct.put(dynamicTypemembers);
            }
        }
        return members;
    }
    {
        return Context.reportRuntimeError2(
            "msg.java.member.not.found".getName(), memberName);
    }
    private Class<?> cl;
    private Map<String,Objectmembers;
    private Map<String,ObjectstaticMembers;
    NativeJavaMethod ctors// we use NativeJavaMethod for ctor overload resolution
    BeanProperty(MemberBox getterMemberBox setterNativeJavaMethod setters)
    {
        this. = getter;
        this. = setter;
        this. = setters;
    }
    static final long serialVersionUID = -9222428244284796755L;
    FieldAndMethods(Scriptable scopeMemberBox[] methodsField field)
    {
        super(methods);
        this. = field;
        setParentScope(scope);
        setPrototype(ScriptableObject.getFunctionPrototype(scope));
    }
    @Override
    public Object getDefaultValue(Class<?> hint)
    {
        if (hint == .)
            return this;
        Object rval;
        Class<?> type;
        try {
            rval = .get();
            type = .getType();
        } catch (IllegalAccessException accEx) {
            throw Context.reportRuntimeError1(
                "msg.java.internal.private".getName());
        }
        Context cx  = Context.getContext();
        rval = cx.getWrapFactory().wrap(cxthisrvaltype);
        if (rval instanceof Scriptable) {
            rval = ((Scriptablerval).getDefaultValue(hint);
        }
        return rval;
    }
    Field field;