1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package groovy.lang;
19
20 import java.lang.reflect.Method;
21 import java.util.List;
22 import java.util.logging.Logger;
23
24 import org.codehaus.groovy.ast.ClassNode;
25 import org.codehaus.groovy.runtime.MetaClassHelper;
26
27 /***
28 * Base class for meta class implementations.
29 * The meta class is used to invoke methods or to get
30 * fields/properties. For proper initialization of this class
31 * it is not enough to only call the constructor, the
32 * initialize() must be called too. The invoke methods should
33 * check that initialize() was called. Adding methods is
34 * valid unless initilise method was called. Therefore
35 * addNewStaticMethod and addNewInstanceMethod should check that
36 * that initilise awas not called before.
37 *
38 *
39 * @author John Wilson
40 *
41 */
42
43 public abstract class MetaClass {
44 protected static final Logger log = Logger.getLogger(MetaClass.class.getName());
45 protected static boolean useReflection = false;
46 public static final Object NO_METHOD_FOUND = new Object();
47 protected final Class theClass;
48 private boolean isGroovyObject;
49
50 public static boolean isUseReflection() {
51 return MetaClass.useReflection;
52 }
53
54 /***
55 * Allows reflection to be enabled in situations where bytecode generation
56 * of method invocations causes issues.
57 *
58 * @param useReflection
59 */
60 public static void setUseReflection(boolean useReflection) {
61 MetaClass.useReflection = useReflection;
62 }
63
64 protected MetaClass(final Class theClass) {
65 this.theClass = theClass;
66 isGroovyObject = GroovyObject.class.isAssignableFrom(theClass);
67 }
68
69 public boolean isGroovyObject(){
70 return isGroovyObject;
71 }
72
73 public Object invokeMissingMethod(Object instance, String methodName, Object[] arguments) {
74 GroovyObject pogo = (GroovyObject) instance;
75 return pogo.invokeMethod(methodName,arguments);
76 }
77
78 public Object invokeMethod(Object object, String methodName, Object arguments) {
79 if (arguments == null) {
80 return invokeMethod(object, methodName, MetaClassHelper.EMPTY_ARRAY);
81 }
82 if (arguments instanceof Tuple) {
83 Tuple tuple = (Tuple) arguments;
84 return invokeMethod(object, methodName, tuple.toArray());
85 }
86 if (arguments instanceof Object[]) {
87 return invokeMethod(object, methodName, (Object[])arguments);
88 }
89 else {
90 return invokeMethod(object, methodName, new Object[]{arguments});
91 }
92 }
93
94 public Object invokeMethod(Class sender, Object receiver, String methodName, Object[] arguments, boolean isCallToSuper, boolean fromInsideClass){
95 return invokeMethod(receiver,methodName,arguments);
96 }
97
98 public Object getProperty(Class sender, Object receiver, String messageName, boolean useSuper, boolean fromInsideClass) {
99 return getProperty(receiver,messageName);
100 }
101
102 public void setProperty(Class sender, Object receiver, String messageName, Object messageValue, boolean useSuper, boolean fromInsideClass) {
103 setProperty(receiver,messageName,messageValue);
104 }
105
106 public Object getAttribute(Class sender, Object receiver, String messageName, boolean useSuper) {
107 return getAttribute(receiver,messageName);
108 }
109
110 public void setAttribute(Class sender, Object receiver, String messageName, Object messageValue, boolean useSuper, boolean fromInsideClass) {
111 setAttribute(receiver,messageName,messageValue);
112 }
113
114 public abstract Object invokeConstructor(Object[] arguments);
115 public abstract Object invokeMethod(Object object, String methodName, Object[] arguments);
116 public abstract Object invokeStaticMethod(Object object, String methodName, Object[] arguments);
117 public abstract Object getProperty(Object object, String property);
118 public abstract void setProperty(Object object, String property, Object newValue);
119 public abstract Object getAttribute(Object object, String attribute);
120 public abstract void setAttribute(Object object, String attribute, Object newValue);
121 /***
122 * adds a new instance method to this meta class. Instance
123 * methods are able to overwrite the original methods of the
124 * class. Calling this method should not be done after
125 * initlise was called.
126 * @param method the method to be added
127 */
128 public abstract void addNewInstanceMethod(Method method);
129 /***
130 * adds a new static method to this meta class. This is only
131 * possible as long as initilise was not called.
132 * @param method the method to be added
133 */
134 public abstract void addNewStaticMethod(Method method);
135 /***
136 * complete the initlialisation process. After this method
137 * is called no methods should be added to the meta class.
138 * Invocation of methods or access to fields/proeprties is
139 * forbidden unless this method is called. This method
140 * should contain any initialisation code, taking a longer
141 * time to complete. An example is the creation of the
142 * Reflector. It is suggested to synchronize this
143 * method.
144 */
145 public abstract void initialize();
146
147 public abstract List getProperties();
148 public abstract ClassNode getClassNode();
149 public abstract List getMetaMethods();
150
151 public abstract List getMethods();
152
153 /***
154 * Warning, this method will be removed
155 * @deprecated use invokeConstructor instead
156 */
157 public Object invokeConstructorAt(Class at, Object[] arguments) {
158 return invokeConstructor(arguments);
159 }
160
161 /***
162 * Selects a method by name and argument classes. This method
163 * does not search for an exact match, it searches for a compatible
164 * method. For this the method selection mechanism is used as provided
165 * bye the implementation of this MetaClass. pickMethod may or may
166 * not used during the method selection process when invoking a method
167 * thereis no warranty for that.
168 *
169 * @returns a matching MetaMethod or null
170 * @throws GroovyRuntimeException if there is more than one matching method
171 */
172 public abstract MetaMethod pickMethod(String methodName, Class[] arguments);
173
174 /***
175 * Warning, this method will be removed
176 * @deprecated usw pickMethod instead
177 */
178 protected MetaMethod retrieveMethod(String methodName, Class[] arguments) {
179 return pickMethod(methodName,arguments);
180 }
181
182 }