📄 metaclassimpl.java
字号:
for (Iterator iter = methods.iterator(); iter.hasNext();) { MetaMethod method = (MetaMethod) iter.next(); if (method.isMethod(aMethod)) { return method; } } //log.warning("Creating reflection based dispatcher for: " + aMethod); return new ReflectionMetaMethod(aMethod); } /** * @return the getter method for the given object */ private MetaMethod findGetter(Object object, String name) { List methods = getMethods(name); for (Iterator iter = methods.iterator(); iter.hasNext();) { MetaMethod method = (MetaMethod) iter.next(); if (method.getParameterTypes().length == 0) { return method; } } return null; } /** * @return the Method of the given name with no parameters or null */ private MetaMethod findStaticGetter(Class type, String name) { List methods = getStaticMethods(name); for (Iterator iter = methods.iterator(); iter.hasNext();) { MetaMethod method = (MetaMethod) iter.next(); if (method.getParameterTypes().length == 0) { return method; } } /** todo dirty hack - don't understand why this code is necessary - all methods should be in the allMethods list! */ try { Method method = type.getMethod(name, MetaClassHelper.EMPTY_TYPE_ARRAY); if ((method.getModifiers() & Modifier.STATIC) != 0) { return findMethod(method); } else { return null; } } catch (Exception e) { return null; } } private static Object doConstructorInvokeAt(final Class at, Constructor constructor, Object[] argumentArray) { if (log.isLoggable(Level.FINER)) { MetaClassHelper.logMethodCall(constructor.getDeclaringClass(), constructor.getName(), argumentArray); } // To fix JIRA 435 // Every constructor should be opened to the accessible classes. final boolean accessible = MetaClassHelper.accessibleToConstructor(at, constructor); final Constructor ctor = constructor; AccessController.doPrivileged(new PrivilegedAction() { public Object run() { ctor.setAccessible(accessible); return null; } }); return MetaClassHelper.doConstructorInvoke(constructor,argumentArray); } /** * Chooses the correct method to use from a list of methods which match by * name. * * @param methods * the possible methods to choose from * @param arguments * the original argument to the method * @return */ private Object chooseMethod(String methodName, List methods, Class[] arguments, boolean coerce) { int methodCount = methods.size(); if (methodCount <= 0) { return null; } else if (methodCount == 1) { Object method = methods.get(0); if (MetaClassHelper.isValidMethod(method, arguments, coerce)) { return method; } return null; } Object answer = null; if (arguments == null || arguments.length == 0) { answer = MetaClassHelper.chooseEmptyMethodParams(methods); } else if (arguments.length == 1 && arguments[0] == null) { answer = MetaClassHelper.chooseMostGeneralMethodWith1NullParam(methods); } else { List matchingMethods = new ArrayList(); for (Iterator iter = methods.iterator(); iter.hasNext();) { Object method = iter.next(); // making this false helps find matches if (MetaClassHelper.isValidMethod(method, arguments, coerce)) { matchingMethods.add(method); } } if (matchingMethods.isEmpty()) { return null; } else if (matchingMethods.size() == 1) { return matchingMethods.get(0); } return chooseMostSpecificParams(methodName, matchingMethods, arguments); } if (answer != null) { return answer; } throw new GroovyRuntimeException( "Could not find which method to invoke from this list: " + methods + " for arguments: " + InvokerHelper.toString(arguments)); } private Object chooseMostSpecificParams(String name, List matchingMethods, Class[] arguments) { Class[] wrappedArguments = MetaClassHelper.wrap(arguments); int matchesDistance = -1; LinkedList matches = new LinkedList(); for (Iterator iter = matchingMethods.iterator(); iter.hasNext();) { Object method = iter.next(); Class[] paramTypes = MetaClassHelper.getParameterTypes(method); if (!MetaClassHelper.parametersAreCompatible(arguments, paramTypes)) continue; int dist = MetaClassHelper.calculateParameterDistance(arguments, paramTypes); if (matches.size()==0) { matches.add(method); matchesDistance = dist; } else if (dist<matchesDistance) { matchesDistance=dist; matches.clear(); matches.add(method); } else if (dist==matchesDistance) { matches.add(method); } } if (matches.size()==1) { return matches.getFirst(); } if (matches.size()==0) { return null; } //more than one matching method found --> ambigous! String msg = "Ambiguous method overloading for method "; msg+= theClass.getName()+"#"+name; msg+= ".\nCannot resolve which method to invoke for "; msg+= InvokerHelper.toString(arguments); msg+= " due to overlapping prototypes between:"; for (Iterator iter = matches.iterator(); iter.hasNext();) { Class[] types=MetaClassHelper.getParameterTypes(iter.next()); msg+= "\n\t"+InvokerHelper.toString(types); } throw new GroovyRuntimeException(msg); } private boolean isGenericGetMethod(MetaMethod method) { if (method.getName().equals("get")) { Class[] parameterTypes = method.getParameterTypes(); return parameterTypes.length == 1 && parameterTypes[0] == String.class; } return false; } /** * Call this method when any mutation method is called, such as adding a new * method to this MetaClass so that any caching or bytecode generation can be * regenerated. */ private synchronized void onMethodChange() { reflector = null; } public synchronized void checkInitialised() { if (!initialised) { initialised = true; addInheritedMethods(); } if (reflector == null) { generateReflector(); } } private MetaMethod createMetaMethod(final Method method) { if (registry.useAccessible()) { AccessController.doPrivileged(new PrivilegedAction() { public Object run() { method.setAccessible(true); return null; } }); } MetaMethod answer = new MetaMethod(method); if (isValidReflectorMethod(answer)) { allMethods.add(answer); answer.setMethodIndex(allMethods.size()); } else { //log.warning("Creating reflection based dispatcher for: " + method); answer = new ReflectionMetaMethod(method); } if (useReflection) { //log.warning("Creating reflection based dispatcher for: " + method); return new ReflectionMetaMethod(method); } return answer; } private boolean isValidReflectorMethod(MetaMethod method) { // We cannot use a reflector if the method is private, protected, or package accessible only. if (!method.isPublic()) { return false; } // lets see if this method is implemented on an interface List interfaceMethods = getInterfaceMethods(); for (Iterator iter = interfaceMethods.iterator(); iter.hasNext();) { MetaMethod aMethod = (MetaMethod) iter.next(); if (method.isSame(aMethod)) { method.setInterfaceClass(aMethod.getDeclaringClass()); return true; } } // it's no interface method, so try to find the highest class // in hierarchy defining this method Class declaringClass = method.getDeclaringClass(); for (Class clazz=declaringClass; clazz!=null; clazz=clazz.getSuperclass()) { try { final Class klazz = clazz; final String mName = method.getName(); final Class[] parms = method.getParameterTypes(); try { Method m = (Method) AccessController.doPrivileged(new PrivilegedExceptionAction() { public Object run() throws NoSuchMethodException { return klazz.getDeclaredMethod(mName, parms); } }); if (!Modifier.isPublic(clazz.getModifiers())) continue; if (!Modifier.isPublic(m.getModifiers())) continue; declaringClass = clazz; } catch (PrivilegedActionException pae) { if (pae.getException() instanceof NoSuchMethodException) { throw (NoSuchMethodException) pae.getException(); } else { throw new RuntimeException(pae.getException()); } } } catch (SecurityException e) { continue; } catch (NoSuchMethodException e) { continue; } } if (!Modifier.isPublic(declaringClass.getModifiers())) return false; method.setDeclaringClass(declaringClass); return true; } private void generateReflector() { reflector = loadReflector(allMethods); if (reflector == null) { throw new RuntimeException("Should have a reflector for "+theClass.getName()); } // lets set the reflector on all the methods for (Iterator iter = allMethods.iterator(); iter.hasNext();) { MetaMethod metaMethod = (MetaMethod) iter.next(); metaMethod.setReflector(reflector); } } private String getReflectorName() { String className = theClass.getName(); String packagePrefix = "gjdk."; String name = packagePrefix + className + "_GroovyReflector"; if (theClass.isArray()) { Class clazz = theClass; name = packagePrefix; int level = 0; while (clazz.isArray()) { clazz = clazz.getComponentType(); level++; } String componentName = clazz.getName(); name = packagePrefix + componentName + "_GroovyReflectorArray"; if (level>1) name += level; } return name; } private Reflector loadReflector(List methods) { String name = getReflectorName(); /* * Lets generate it && load it. */ ReflectorGenerator generator = new ReflectorGenerator(methods); try { ClassWriter cw = new ClassWriter(true); generator.generate(cw, name); byte[] bytecode = cw.toByteArray(); /*try { FileOutputStream fis = new FileOutputStream(name); fis.write(bytecode); fis.close(); } catch (IOException ioe){}*/ ClassLoader loader = (ClassLoader) AccessController.doPrivileged(new PrivilegedAction() { public Object run() { return theClass.getClassLoader(); } }); Class type = registry.createReflectorClass(loader, nam
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -