1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 package groovy.lang;
36
37 import java.lang.reflect.Method;
38 import java.lang.reflect.Modifier;
39 import java.security.AccessController;
40 import java.security.PrivilegedAction;
41 import java.util.logging.Logger;
42
43 import org.codehaus.groovy.runtime.InvokerHelper;
44 import org.codehaus.groovy.runtime.MetaClassHelper;
45 import org.codehaus.groovy.runtime.Reflector;
46
47 /***
48 * Represents a Method on a Java object a little like {@link java.lang.reflect.Method}
49 * except without using reflection to invoke the method
50 *
51 * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
52 * @version $Revision: 1.18 $
53 */
54 public class MetaMethod implements Cloneable {
55
56 private static final Logger log = Logger.getLogger(MetaMethod.class.getName());
57
58 private String name;
59 private Class declaringClass;
60 private Class interfaceClass;
61 private Class[] parameterTypes;
62 private Class returnType;
63 private int modifiers;
64 private Reflector reflector;
65 private int methodIndex;
66 private Method method;
67
68 public MetaMethod(String name, Class declaringClass, Class[] parameterTypes, Class returnType, int modifiers) {
69 this.name = name;
70 this.declaringClass = declaringClass;
71 this.parameterTypes = parameterTypes;
72 this.returnType = returnType;
73 this.modifiers = modifiers;
74 }
75
76 public MetaMethod(Method method) {
77 this(
78 method.getName(),
79 method.getDeclaringClass(),
80 method.getParameterTypes(),
81 method.getReturnType(),
82 method.getModifiers());
83 this.method = method;
84 }
85
86 public MetaMethod(MetaMethod metaMethod) {
87 this(metaMethod.method);
88 }
89
90 /***
91 * Checks that the given parameters are valid to call this method
92 *
93 * @param arguments
94 * @throws IllegalArgumentException if the parameters are not valid
95 */
96 public void checkParameters(Class[] arguments) {
97
98 if (!MetaClassHelper.isValidMethod(getParameterTypes(), arguments, false)) {
99 throw new IllegalArgumentException(
100 "Parameters to method: "
101 + getName()
102 + " do not match types: "
103 + InvokerHelper.toString(getParameterTypes())
104 + " for arguments: "
105 + InvokerHelper.toString(arguments));
106 }
107 }
108
109 public Object invoke(Object object, Object[] arguments) throws Exception {
110 if (reflector != null) {
111 return reflector.invoke(this, object, arguments);
112 }
113 else {
114 AccessController.doPrivileged(new PrivilegedAction() {
115 public Object run() {
116 method.setAccessible(true);
117 return null;
118 }
119 });
120 return method.invoke(object, arguments);
121 }
122 }
123
124 public Class getDeclaringClass() {
125 return declaringClass;
126 }
127
128 public void setDeclaringClass(Class c) {
129 declaringClass=c;
130 }
131
132 public int getMethodIndex() {
133 return methodIndex;
134 }
135
136 public void setMethodIndex(int methodIndex) {
137 this.methodIndex = methodIndex;
138 }
139
140 public int getModifiers() {
141 return modifiers;
142 }
143
144 public String getName() {
145 return name;
146 }
147
148 public Class[] getParameterTypes() {
149 return parameterTypes;
150 }
151
152 public Class getReturnType() {
153 return returnType;
154 }
155
156 public Reflector getReflector() {
157 return reflector;
158 }
159
160 public void setReflector(Reflector reflector) {
161 this.reflector = reflector;
162 }
163
164 public boolean isMethod(Method method) {
165 return name.equals(method.getName())
166 && modifiers == method.getModifiers()
167 && returnType.equals(method.getReturnType())
168 && equal(parameterTypes, method.getParameterTypes());
169 }
170
171 protected boolean equal(Class[] a, Class[] b) {
172 if (a.length == b.length) {
173 for (int i = 0, size = a.length; i < size; i++) {
174 if (!a[i].equals(b[i])) {
175 return false;
176 }
177 }
178 return true;
179 }
180 return false;
181 }
182
183 public String toString() {
184 return super.toString()
185 + "[name: "
186 + name
187 + " params: "
188 + InvokerHelper.toString(parameterTypes)
189 + " returns: "
190 + returnType
191 + " owner: "
192 + declaringClass
193 + "]";
194 }
195
196 public Object clone() {
197 try {
198 return super.clone();
199 }
200 catch (CloneNotSupportedException e) {
201 throw new GroovyRuntimeException("This should never happen", e);
202 }
203 }
204
205 public boolean isStatic() {
206 return (modifiers & Modifier.STATIC) != 0;
207 }
208
209 public boolean isPrivate() {
210 return (modifiers & Modifier.PRIVATE) != 0;
211 }
212
213 public boolean isProtected() {
214 return (modifiers & Modifier.PROTECTED) != 0;
215 }
216
217 public boolean isPublic() {
218 return (modifiers & Modifier.PUBLIC) != 0;
219 }
220
221 /***
222 * @return true if the given method has the same name, parameters, return type
223 * and modifiers but may be defined on another type
224 */
225 public boolean isSame(MetaMethod method) {
226 return name.equals(method.getName())
227 && compatibleModifiers(modifiers, method.getModifiers())
228 && returnType.equals(method.getReturnType())
229 && equal(parameterTypes, method.getParameterTypes());
230 }
231
232 protected boolean compatibleModifiers(int modifiersA, int modifiersB) {
233 int mask = Modifier.PRIVATE | Modifier.PROTECTED | Modifier.PUBLIC | Modifier.STATIC;
234 return (modifiersA & mask) == (modifiersB & mask);
235 }
236
237 public Class getInterfaceClass() {
238 return interfaceClass;
239 }
240
241 public void setInterfaceClass(Class interfaceClass) {
242 this.interfaceClass = interfaceClass;
243 }
244
245 public boolean isCacheable() {
246 return true;
247 }
248
249 }