static JavaMembers lookupClass( Scriptable scope, Class<?> dynamicType, Class<?> staticType, boolean includeProtected) { JavaMembers members; ClassCache cache = ClassCache.get(scope); Map<Class<?>, JavaMembers> ct = 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(dynamicType, members); } 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 = ScriptRuntime.ObjectClass; } else { throw e; } } cl = parent; } } } if (cache.isCachingEnabled()) { ct.put(cl, members); 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(dynamicType, members); } } return members; }
/** * Make glue object implementing interface cl that will call the supplied JS function when called. * Only interfaces were all methods have the same signature is supported. * * @return The glue object or null if <tt>cl</tt> is not interface or has methods with different * signatures. */ static Object create(Context cx, Class<?> cl, Callable function) { if (!cl.isInterface()) throw new IllegalArgumentException(); Scriptable topScope = ScriptRuntime.getTopCallScope(cx); ClassCache cache = ClassCache.get(topScope); InterfaceAdapter adapter; adapter = (InterfaceAdapter) cache.getInterfaceAdapter(cl); ContextFactory cf = cx.getFactory(); if (adapter == null) { Method[] methods = cl.getMethods(); if (methods.length == 0) { throw Context.reportRuntimeError2( "msg.no.empty.interface.conversion", String.valueOf(function), cl.getClass().getName()); } boolean canCallFunction = false; canCallFunctionChecks: { Class<?>[] argTypes = methods[0].getParameterTypes(); // check that the rest of methods has the same signature for (int i = 1; i != methods.length; ++i) { Class<?>[] types2 = methods[i].getParameterTypes(); if (types2.length != argTypes.length) { break canCallFunctionChecks; } for (int j = 0; j != argTypes.length; ++j) { if (types2[j] != argTypes[j]) { break canCallFunctionChecks; } } } canCallFunction = true; } if (!canCallFunction) { throw Context.reportRuntimeError2( "msg.no.function.interface.conversion", String.valueOf(function), cl.getClass().getName()); } adapter = new InterfaceAdapter(cf, cl); cache.cacheInterfaceAdapter(cl, adapter); } return VMBridge.instance.newInterfaceProxy( adapter.proxyHelper, cf, adapter, function, topScope); }
private static Class<?> getAdapterClass( Scriptable scope, Class<?> superClass, Class<?>[] interfaces, Scriptable obj) { ClassCache cache = ClassCache.get(scope); Map<JavaAdapterSignature, Class<?>> generated = cache.getInterfaceAdapterCacheMap(); ObjToIntMap names = getObjectFunctionNames(obj); JavaAdapterSignature sig; sig = new JavaAdapterSignature(superClass, interfaces, names); Class<?> adapterClass = generated.get(sig); if (adapterClass == null) { String adapterName = "adapter" + cache.newClassSerialNumber(); byte[] code = createAdapterCode(names, adapterName, superClass, interfaces, null); adapterClass = loadAdapterClass(adapterName, code); if (cache.isCachingEnabled()) { generated.put(sig, adapterClass); } } return adapterClass; }