001 /*
002 * Copyright 2005 John G. Wilson
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 */
017
018 package groovy.lang;
019
020 import java.lang.reflect.Method;
021 import java.util.List;
022 import java.util.logging.Logger;
023
024 import org.codehaus.groovy.ast.ClassNode;
025 import org.codehaus.groovy.runtime.MetaClassHelper;
026
027 /**
028 * Base class for meta class implementations.
029 * The meta class is used to invoke methods or to get
030 * fields/properties. For proper initialization of this class
031 * it is not enough to only call the constructor, the
032 * initialize() must be called too. The invoke methods should
033 * check that initialize() was called. Adding methods is
034 * valid unless initilise method was called. Therefore
035 * addNewStaticMethod and addNewInstanceMethod should check that
036 * that initilise awas not called before.
037 *
038 *
039 * @author John Wilson
040 *
041 */
042
043 public abstract class MetaClass {
044 protected static final Logger log = Logger.getLogger(MetaClass.class.getName());
045 protected static boolean useReflection = false;
046 public static final Object NO_METHOD_FOUND = new Object();
047 protected final Class theClass;
048 private boolean isGroovyObject;
049
050 public static boolean isUseReflection() {
051 return MetaClass.useReflection;
052 }
053
054 /**
055 * Allows reflection to be enabled in situations where bytecode generation
056 * of method invocations causes issues.
057 *
058 * @param useReflection
059 */
060 public static void setUseReflection(boolean useReflection) {
061 MetaClass.useReflection = useReflection;
062 }
063
064 protected MetaClass(final Class theClass) {
065 this.theClass = theClass;
066 isGroovyObject = GroovyObject.class.isAssignableFrom(theClass);
067 }
068
069 public boolean isGroovyObject(){
070 return isGroovyObject;
071 }
072
073 public Object invokeMissingMethod(Object instance, String methodName, Object[] arguments) {
074 GroovyObject pogo = (GroovyObject) instance;
075 return pogo.invokeMethod(methodName,arguments);
076 }
077
078 public Object invokeMethod(Object object, String methodName, Object arguments) {
079 if (arguments == null) {
080 return invokeMethod(object, methodName, MetaClassHelper.EMPTY_ARRAY);
081 }
082 if (arguments instanceof Tuple) {
083 Tuple tuple = (Tuple) arguments;
084 return invokeMethod(object, methodName, tuple.toArray());
085 }
086 if (arguments instanceof Object[]) {
087 return invokeMethod(object, methodName, (Object[])arguments);
088 }
089 else {
090 return invokeMethod(object, methodName, new Object[]{arguments});
091 }
092 }
093
094 public Object invokeMethod(Class sender, Object receiver, String methodName, Object[] arguments, boolean isCallToSuper, boolean fromInsideClass){
095 return invokeMethod(receiver,methodName,arguments);
096 }
097
098 public Object getProperty(Class sender, Object receiver, String messageName, boolean useSuper, boolean fromInsideClass) {
099 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 until 1.0
155 * @deprecated
156 */
157 public Object invokeConstructorAt(Class at, Object[] arguments) {
158 return invokeConstructor(arguments);
159 }
160
161 /**
162 * Warning, this method will be removed until 1.0
163 * @deprecated
164 */
165 public abstract MetaMethod pickMethod(String methodName, Class[] arguments);
166
167 /**
168 * Warning, this method will be removed until 1.0
169 * @deprecated
170 */
171 protected abstract MetaMethod retrieveMethod(String methodName, Class[] arguments);
172
173 }