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 }