A meta class for closures generated by the Groovy compiler. These classes
have special characteristics this MetaClass uses. One of these is that a
generated Closure has only additional doCall methods, all other methods
are in the Closure class as well. To use this fact this MetaClass uses
a MetaClass for Closure as static field And delegates calls to this
MetaClass if needed. This allows a lean implementation for this MetaClass.
Multiple generated closures will then use the same MetaClass for Closure.
For static dispatching this class uses the MetaClass of Class, again
all instances of this class will share that MetaClass. The Class MetaClass
is initialized lazy, because most operations do not need this MetaClass.
| Method from org.codehaus.groovy.runtime.metaclass.ClosureMetaClass Detail: |
public void addMetaBeanProperty(MetaBeanProperty mp) {
throw new UnsupportedOperationException();
}
|
public void addMetaMethod(MetaMethod method) {
throw new UnsupportedOperationException();
}
|
public void addNewInstanceMethod(Method method) {
throw new UnsupportedOperationException();
}
|
public void addNewStaticMethod(Method method) {
throw new UnsupportedOperationException();
}
|
public CallSite createPogoCallCurrentSite(CallSite site,
Class sender,
Object[] args) {
return new PogoMetaClassSite(site, this);
}
|
public CallSite createPogoCallSite(CallSite site,
Object[] args) {
return new PogoMetaClassSite(site, this);
}
|
public CallSite createPojoCallSite(CallSite site,
Object receiver,
Object[] args) {
throw new UnsupportedOperationException();
}
|
public Object getAttribute(Class sender,
Object object,
String attribute,
boolean useSuper,
boolean fromInsideClass) {
if (object instanceof Class) {
return getStaticMetaClass().getAttribute(sender, object, attribute, useSuper);
} else {
if (!attributeInitDone) initAttributes();
CachedField mfp = (CachedField) attributes.get(attribute);
if (mfp == null) {
return CLOSURE_METACLASS.getAttribute(sender, object, attribute, useSuper);
} else {
return mfp.getProperty(object);
}
}
}
|
public List<MetaMethod> getMetaMethods() {
return CLOSURE_METACLASS.getMetaMethods();
}
|
public MetaProperty getMetaProperty(String name) {
return CLOSURE_METACLASS.getMetaProperty(name);
}
|
public MetaMethod getMethodWithoutCaching(int index,
Class sender,
String methodName,
Class[] arguments,
boolean isCallToSuper) {
throw new UnsupportedOperationException();
}
|
public List<MetaMethod> getMethods() {
List< MetaMethod > answer = CLOSURE_METACLASS.getMetaMethods();
answer.addAll(closureMethods.toList());
return answer;
}
|
public List<MetaProperty> getProperties() {
return CLOSURE_METACLASS.getProperties();
}
|
public Object getProperty(Class sender,
Object object,
String name,
boolean useSuper,
boolean fromInsideClass) {
if (object instanceof Class) {
return getStaticMetaClass().getProperty(sender, object, name, useSuper, fromInsideClass);
} else {
return CLOSURE_METACLASS.getProperty(sender, object, name, useSuper, fromInsideClass);
}
}
|
public MetaMethod getStaticMetaMethod(String name,
Object[] args) {
return CLOSURE_METACLASS.getStaticMetaMethod(name, args);
}
|
public MetaMethod getStaticMetaMethod(String name,
Class[] argTypes) {
return CLOSURE_METACLASS.getStaticMetaMethod(name, argTypes);
}
|
public synchronized void initialize() {
if (!isInitialized()) {
CachedMethod[] methodArray = theCachedClass.getMethods();
synchronized (theCachedClass) {
for (int i = 0; i < methodArray.length; i++) {
final CachedMethod cachedMethod = methodArray[i];
if (!cachedMethod.getName().equals(CLOSURE_DO_CALL_METHOD)) continue;
MetaMethod method = cachedMethod;
closureMethods.add(method);
}
}
assignMethodChooser();
initialized = true;
}
}
|
public Object invokeMethod(Class sender,
Object object,
String methodName,
Object[] originalArguments,
boolean isCallToSuper,
boolean fromInsideClass) {
checkInitalised();
if (object == null) {
throw new NullPointerException("Cannot invoke method: " + methodName + " on null object");
}
final Object[] arguments = makeArguments(originalArguments, methodName);
final Class[] argClasses = MetaClassHelper.convertToTypeArray(arguments);
unwrap(arguments);
MetaMethod method;
final Closure closure = (Closure) object;
if (CLOSURE_DO_CALL_METHOD.equals(methodName) || CLOSURE_CALL_METHOD.equals(methodName)) {
method = pickClosureMethod(argClasses);
if (method==null && arguments.length==1 && arguments[0] instanceof List) {
Object[] newArguments = ((List) arguments[0]).toArray();
Class[] newArgClasses = MetaClassHelper.convertToTypeArray(newArguments);
method = pickClosureMethod(newArgClasses);
if (method!=null) {
method = new TransformMetaMethod(method) {
public Object invoke(Object object, Object[] arguments) {
Object firstArgument = arguments[0];
List list = (List) firstArgument;
arguments = list.toArray();
return super.invoke(object, arguments);
}
};
}
}
if (method==null) throw new MissingMethodException(methodName, theClass, arguments, false);
} else if (CLOSURE_CURRY_METHOD.equals(methodName)) {
return closure.curry(arguments);
} else {
method = CLOSURE_METACLASS.pickMethod(methodName, argClasses);
}
if (method != null) return method.doMethodInvoke(object, arguments);
MissingMethodException last = null;
Object callObject = object;
if (method == null) {
final Object owner = closure.getOwner();
final Object delegate = closure.getDelegate();
final Object thisObject = closure.getThisObject();
final int resolveStrategy = closure.getResolveStrategy();
boolean invokeOnDelegate = false;
boolean invokeOnOwner = false;
boolean ownerFirst = true;
switch (resolveStrategy) {
case Closure.TO_SELF:
break;
case Closure.DELEGATE_ONLY:
method = getDelegateMethod(closure, delegate, methodName, argClasses);
callObject = delegate;
if (method == null) {
invokeOnDelegate = delegate != closure && (delegate instanceof GroovyObject);
}
break;
case Closure.OWNER_ONLY:
method = getDelegateMethod(closure, owner, methodName, argClasses);
callObject = owner;
if (method == null) {
invokeOnOwner = owner != closure && (owner instanceof GroovyObject);
}
break;
case Closure.DELEGATE_FIRST:
method = getDelegateMethod(closure, delegate, methodName, argClasses);
callObject = delegate;
if (method == null) {
method = getDelegateMethod(closure, owner, methodName, argClasses);
callObject = owner;
}
if (method == null) {
invokeOnDelegate = delegate != closure && (delegate instanceof GroovyObject);
invokeOnOwner = owner != closure && (owner instanceof GroovyObject);
ownerFirst = false;
}
break;
default: // owner first
// owner first means we start with the outer most owner that is not a generated closure
// this owner is equal to the this object, so we check that one first.
method = getDelegateMethod(closure, thisObject, methodName, argClasses);
callObject = thisObject;
if (method == null) {
//try finding a delegate that has that method... we start from
// outside building a stack and try each delegate
LinkedList list = new LinkedList();
for (Object current = closure; current!=thisObject; ) {
Closure currentClosure = (Closure) current;
if (currentClosure.getDelegate()!=null) list.add(current);
current=currentClosure.getOwner();
}
while (!list.isEmpty() && method==null) {
Closure closureWithDelegate = (Closure) list.removeLast();
Object currentDelegate = closureWithDelegate.getDelegate();
method = getDelegateMethod(closureWithDelegate,currentDelegate,methodName,argClasses);
callObject = currentDelegate;
}
}
if (method == null) {
invokeOnDelegate = delegate != closure && (delegate instanceof GroovyObject);
invokeOnOwner = owner != closure && (owner instanceof GroovyObject);
}
}
if (method == null && (invokeOnOwner || invokeOnDelegate)) {
try {
if (ownerFirst) {
return invokeOnDelegationObjects(invokeOnOwner, owner, invokeOnDelegate, delegate, methodName, arguments);
} else {
return invokeOnDelegationObjects(invokeOnDelegate, delegate, invokeOnOwner, owner, methodName, arguments);
}
} catch (MissingMethodException mme) {
last = mme;
}
}
}
if (method != null) {
MetaClass metaClass = registry.getMetaClass(callObject.getClass());
if(metaClass instanceof ProxyMetaClass) {
return metaClass.invokeMethod(callObject, methodName, arguments);
} else {
return method.doMethodInvoke(callObject, arguments);
}
} else {
// if no method was found, try to find a closure defined as a field of the class and run it
Object value = null;
try {
value = this.getProperty(object, methodName);
} catch (MissingPropertyException mpe) {
// ignore
}
if (value instanceof Closure) { // This test ensures that value != this If you ever change this ensure that value != this
Closure cl = (Closure) value;
MetaClass delegateMetaClass = cl.getMetaClass();
return delegateMetaClass.invokeMethod(cl.getClass(), closure, CLOSURE_DO_CALL_METHOD, originalArguments, false, fromInsideClass);
}
}
if (last != null) throw last;
throw new MissingMethodException(methodName, theClass, arguments, false);
}
|
public Object invokeStaticMethod(Object object,
String methodName,
Object[] arguments) {
return getStaticMetaClass().invokeMethod(Class.class, object, methodName, arguments, false, false);
}
|
protected boolean isInitialized() {
return initialized;
}
|
public MetaMethod pickMethod(String name,
Class[] argTypes) {
if (argTypes == null) argTypes = MetaClassHelper.EMPTY_CLASS_ARRAY;
if (name.equals(CLOSURE_CALL_METHOD) || name.equals(CLOSURE_DO_CALL_METHOD)) {
return pickClosureMethod(argTypes);
}
return CLOSURE_METACLASS.getMetaMethod(name, argTypes);
}
|
public Constructor retrieveConstructor(Class[] arguments) {
throw new UnsupportedOperationException();
}
|
public MetaMethod retrieveStaticMethod(String methodName,
Class[] arguments) {
return null;
}
|
public void setAttribute(Class sender,
Object object,
String attribute,
Object newValue,
boolean useSuper,
boolean fromInsideClass) {
if (object instanceof Class) {
getStaticMetaClass().setAttribute(sender, object, attribute, newValue, useSuper, fromInsideClass);
} else {
if (!attributeInitDone) initAttributes();
CachedField mfp = (CachedField) attributes.get(attribute);
if (mfp == null) {
CLOSURE_METACLASS.setAttribute(sender, object, attribute, newValue, useSuper, fromInsideClass);
} else {
mfp.setProperty(object, newValue);
}
}
}
|
public void setProperties(Object bean,
Map map) {
throw new UnsupportedOperationException();
}
|
public void setProperty(Class sender,
Object object,
String name,
Object newValue,
boolean useSuper,
boolean fromInsideClass) {
if (object instanceof Class) {
getStaticMetaClass().setProperty(sender, object, name, newValue, useSuper, fromInsideClass);
} else {
CLOSURE_METACLASS.setProperty(sender, object, name, newValue, useSuper, fromInsideClass);
}
}
|