📄 metaclassimpl.java
字号:
Object[] arguments = {property, newValue}; Object answer = MetaClassHelper.doMethodInvoke(object, mmethod, arguments); return; } } } } else { Object[] arguments = { property, newValue }; MetaClassHelper.doMethodInvoke(object, genericSetMethod, arguments); return; } /** todo or are we an extensible class? */ // lets try invoke the set method // this is kind of ugly: if it is a protected field, we fall // all the way down to this klunky code. Need a better // way to handle this situation... String method = "set" + MetaClassHelper.capitalize(property); try { invokeMethod(object, method, new Object[] { newValue }); } catch (MissingMethodException e1) { setAttribute(object,property,newValue); } } catch (GroovyRuntimeException e) { runtimeException = e; } if (addListenerMethod==AMBIGOUS_LISTENER_METHOD){ throw new GroovyRuntimeException("There are multiple listeners for the property "+property+". Please do not use the bean short form to access this listener."); } else if (runtimeException!=null) { throw new MissingPropertyException(property, theClass, runtimeException); } } /** * Looks up the given attribute (field) on the given object */ public Object getAttribute(final Object object, final String attribute) { PrivilegedActionException firstException = null; final Class clazz; if (object instanceof Class) { clazz=(Class) object; } else { clazz=theClass; } try { return AccessController.doPrivileged(new PrivilegedExceptionAction() { public Object run() throws NoSuchFieldException, IllegalAccessException { final Field field = clazz.getDeclaredField(attribute); field.setAccessible(true); return field.get(object); } }); } catch (final PrivilegedActionException pae) { firstException = pae; } try { return AccessController.doPrivileged(new PrivilegedExceptionAction() { public Object run() throws NoSuchFieldException, IllegalAccessException { final Field field = clazz.getField(attribute); field.setAccessible(true); return field.get(object); } }); } catch (final PrivilegedActionException pae) { // prefere the first exception. } if (firstException.getException() instanceof NoSuchFieldException) { throw new MissingFieldException(attribute, theClass); } else { throw new RuntimeException(firstException.getException()); } } /** * Sets the given attribute (field) on the given object */ public void setAttribute(final Object object, final String attribute, final Object newValue) { PrivilegedActionException firstException = null; final Class clazz; if (object instanceof Class) { clazz=(Class) object; } else { clazz=theClass; } try { AccessController.doPrivileged(new PrivilegedExceptionAction() { public Object run() throws NoSuchFieldException, IllegalAccessException { final Field field = clazz.getDeclaredField(attribute); field.setAccessible(true); field.set(object,newValue); return null; } }); return; } catch (final PrivilegedActionException pae) { firstException = pae; } try { AccessController.doPrivileged(new PrivilegedExceptionAction() { public Object run() throws NoSuchFieldException, IllegalAccessException { final Field field = clazz.getField(attribute); field.setAccessible(true); field.set(object, newValue); return null; } }); return; } catch (final PrivilegedActionException pae) { // prefere the first exception. } if (firstException.getException() instanceof NoSuchFieldException) { throw new MissingFieldException(attribute, theClass); } else { throw new RuntimeException(firstException.getException()); } } public ClassNode getClassNode() { if (classNode == null && GroovyObject.class.isAssignableFrom(theClass)) { // lets try load it from the classpath String className = theClass.getName(); String groovyFile = className; int idx = groovyFile.indexOf('$'); if (idx > 0) { groovyFile = groovyFile.substring(0, idx); } groovyFile = groovyFile.replace('.', '/') + ".groovy"; //System.out.println("Attempting to load: " + groovyFile); URL url = theClass.getClassLoader().getResource(groovyFile); if (url == null) { url = Thread.currentThread().getContextClassLoader().getResource(groovyFile); } if (url != null) { try { /** * todo there is no CompileUnit in scope so class name * checking won't work but that mostly affects the bytecode * generation rather than viewing the AST */ CompilationUnit.ClassgenCallback search = new CompilationUnit.ClassgenCallback() { public void call( ClassVisitor writer, ClassNode node ) { if( node.getName().equals(theClass.getName()) ) { MetaClassImpl.this.classNode = node; } } }; final ClassLoader parent = theClass.getClassLoader(); GroovyClassLoader gcl = (GroovyClassLoader) AccessController.doPrivileged(new PrivilegedAction() { public Object run() { return new GroovyClassLoader(parent); } }); CompilationUnit unit = new CompilationUnit( ); unit.setClassgenCallback( search ); unit.addSource( url ); unit.compile( Phases.CLASS_GENERATION ); } catch (Exception e) { throw new GroovyRuntimeException("Exception thrown parsing: " + groovyFile + ". Reason: " + e, e); } } } return classNode; } public String toString() { return super.toString() + "[" + theClass + "]"; } // Implementation methods //------------------------------------------------------------------------- /** * Adds all the methods declared in the given class to the metaclass * ignoring any matching methods already defined by a derived class * * @param theClass */ private void addMethods(final Class theClass, boolean forceOverwrite) { // add methods directly declared in the class Method[] methodArray = (Method[]) AccessController.doPrivileged(new PrivilegedAction() { public Object run() { return theClass.getDeclaredMethods(); } }); for (int i = 0; i < methodArray.length; i++) { Method reflectionMethod = methodArray[i]; if ( reflectionMethod.getName().indexOf('+') >= 0 ) { // Skip Synthetic methods inserted by JDK 1.5 compilers and later continue; } MetaMethod method = createMetaMethod(reflectionMethod); addMethod(method,forceOverwrite); } } private void addMethod(MetaMethod method, boolean forceOverwrite) { String name = method.getName(); //System.out.println(theClass.getName() + " == " + name + Arrays.asList(method.getParameterTypes())); if (isGenericGetMethod(method) && genericGetMethod == null) { genericGetMethod = method; } else if (MetaClassHelper.isGenericSetMethod(method) && genericSetMethod == null) { genericSetMethod = method; } if (method.isStatic()) { List list = (List) staticMethodIndex.get(name); if (list == null) { list = new ArrayList(); staticMethodIndex.put(name, list); list.add(method); } else { if (!MetaClassHelper.containsMatchingMethod(list, method)) { list.add(method); } } } List list = (List) methodIndex.get(name); if (list == null) { list = new ArrayList(); methodIndex.put(name, list); list.add(method); } else { if (forceOverwrite) { removeMatchingMethod(list,method); list.add(method); } else if (!MetaClassHelper.containsMatchingMethod(list, method)) { list.add(method); } } } /** * remove a method of the same matching prototype was found in the list */ private void removeMatchingMethod(List list, MetaMethod method) { for (Iterator iter = list.iterator(); iter.hasNext();) { MetaMethod aMethod = (MetaMethod) iter.next(); Class[] params1 = aMethod.getParameterTypes(); Class[] params2 = method.getParameterTypes(); if (params1.length == params2.length) { boolean matches = true; for (int i = 0; i < params1.length; i++) { if (params1[i] != params2[i]) { matches = false; break; } } if (matches) { iter.remove(); return; } } } return; } /** * Adds all of the newly defined methods from the given class to this * metaclass * * @param theClass */ private void addNewStaticMethodsFrom(Class theClass) { MetaClass interfaceMetaClass = registry.getMetaClass(theClass); Iterator iter = interfaceMetaClass.newGroovyMethodsList.iterator(); while (iter.hasNext()) { MetaMethod method = (MetaMethod) iter.next(); if (! newGroovyMethodsList.contains(method)){ newGroovyMethodsList.add(method); addMethod(method,false); } } } /** * @return the value of the static property of the given class */ private Object getStaticProperty(Class aClass, String property) { //System.out.println("Invoking property: " + property + " on class: " // + aClass); // lets try invoke a static getter method MetaMethod method = findStaticGetter(aClass, "get" + MetaClassHelper.capitalize(property)); if (method != null) { return MetaClassHelper.doMethodInvoke(aClass, method, MetaClassHelper.EMPTY_ARRAY); } //no static getter found, try attribute try { return getAttribute(aClass,property); } catch (MissingFieldException mfe) { throw new MissingPropertyException(property, aClass, mfe); } } /** * @return the matching method which should be found */ private MetaMethod findMethod(Method aMethod) { List methods = getMethods(aMethod.getName());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -