001 /*
002 * Copyright 2007-2012 the original author or authors.
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 package org.codehaus.griffon.runtime.builder
017
018 import griffon.util.MethodUtils
019 import java.lang.reflect.InvocationTargetException
020 import org.codehaus.groovy.runtime.InvokerHelper
021 import org.slf4j.Logger
022 import org.slf4j.LoggerFactory
023
024 /**
025 * @author Danno Ferrin
026 * @author Andres Almiray
027 */
028 class UberInterceptorMetaClass extends DelegatingMetaClass {
029 private static final Logger LOG = LoggerFactory.getLogger(UberInterceptorMetaClass)
030 UberBuilder factory
031
032 UberInterceptorMetaClass(MetaClass delegate, UberBuilder factory) {
033 super(delegate)
034 this.factory = factory
035 }
036
037 private Object doInvokeInstanceMethod(Object object, String methodName, Object arguments) {
038 Class klass = object instanceof Class ? object : object.getClass()
039 try {
040 return MethodUtils.invokeMethod(object, methodName, arguments)
041 } catch (NoSuchMethodException nsme) {
042 throw new MissingMethodException(methodName, klass, [arguments] as Object[])
043 } catch (IllegalAccessException iae) {
044 throw new MissingMethodException(methodName, klass, [arguments] as Object[])
045 } catch (InvocationTargetException ite) {
046 throw new MissingMethodException(methodName, klass, [arguments] as Object[])
047 }
048 }
049
050 private Object doInvokeInstanceMethod(Object object, String methodName, Object[] arguments) {
051 Class klass = object instanceof Class ? object : object.getClass()
052 try {
053 return MethodUtils.invokeMethod(object, methodName, arguments)
054 } catch (NoSuchMethodException nsme) {
055 throw new MissingMethodException(methodName, klass, arguments)
056 } catch (IllegalAccessException iae) {
057 throw new MissingMethodException(methodName, klass, arguments)
058 } catch (InvocationTargetException ite) {
059 throw new MissingMethodException(methodName, klass, arguments)
060 }
061 }
062
063 private Object doInvokeStaticMethod(Object object, String methodName, Object[] arguments) {
064 Class klass = object instanceof Class ? object : object.getClass()
065 try {
066 return MethodUtils.invokeStaticMethod(klass, methodName, arguments)
067 } catch (NoSuchMethodException nsme) {
068 throw new MissingMethodException(methodName, klass, arguments)
069 } catch (IllegalAccessException iae) {
070 throw new MissingMethodException(methodName, klass, arguments)
071 } catch (InvocationTargetException ite) {
072 throw new MissingMethodException(methodName, klass, arguments)
073 }
074 }
075
076 private Object invokeFactoryMethod(String methodName, Object arguments, MissingMethodException mme) {
077 try {
078 return factory.invokeMethod(methodName, arguments)
079 } catch (MissingMethodException mme2) {
080 if (mme2.method != methodName) {
081 throw mme2
082 }
083 // chain secondary exception
084 Throwable root = mme
085 while (root.getCause() != null) {
086 root = root.getCause()
087 }
088 root.initCause(mme2)
089 // throw original
090 throw mme
091 }
092 }
093
094 private Object invokeFactoryMethod(String methodName, Object[] arguments, MissingMethodException mme) {
095 try {
096 return factory.invokeMethod(methodName, arguments)
097 } catch (MissingMethodException mme2) {
098 if (mme2.method != methodName) {
099 throw mme2
100 }
101 // chain secondary exception
102 Throwable root = mme
103 while (root.getCause() != null) {
104 root = root.getCause()
105 }
106 root.initCause(mme2)
107 // throw original
108 throw mme
109 }
110 }
111
112 private void exceptionIfMethodNotFound(String methodName, MissingMethodException mme) {
113 if (mme.method != methodName) {
114 throw mme
115 }
116 }
117
118 Object invokeMethod(Object object, String methodName, Object arguments) {
119 // try {
120 // return invokeMethod(object, methodName, arguments);
121 // } catch (MissingMethodException mme) {
122 // exceptionIfMethodNotFound(methodName, mme);
123 try {
124 return delegate.invokeMethod(object, methodName, arguments)
125 } catch (MissingMethodException mme2) {
126 exceptionIfMethodNotFound(methodName, mme2);
127 // attempt method resolution
128 for (UberBuilderRegistration reg in factory.builderRegistration) {
129 try {
130 def builder = reg.builder
131 if (!builder.getMetaClass().respondsTo(builder, methodName).isEmpty()) {
132 return InvokerHelper.invokeMethod(builder, methodName, arguments)
133 }
134 } catch (MissingMethodException mme3) {
135 exceptionIfMethodNotFound(methodName, mme3);
136 // drop the exception, there will be many
137 }
138 }
139 // dispatch to factories if it is not a literal method
140 return invokeFactoryMethod(methodName, arguments, mme2)
141 }
142 // }
143 }
144
145 Object invokeMethod(Object object, String methodName, Object[] arguments) {
146 // try {
147 // return invokeMethod(object, methodName, arguments);
148 // } catch (MissingMethodException mme) {
149 // exceptionIfMethodNotFound(methodName, mme);
150 try {
151 return delegate.invokeMethod(object, methodName, arguments)
152 } catch (MissingMethodException mme2) {
153 exceptionIfMethodNotFound(methodName, mme2);
154 // attempt method resolution
155 for (UberBuilderRegistration reg in factory.builderRegistration) {
156 try {
157 def builder = reg.builder
158 if (!builder.getMetaClass().respondsTo(builder, methodName).isEmpty()) {
159 return InvokerHelper.invokeMethod(builder, methodName, arguments)
160 }
161 } catch (MissingMethodException mme3) {
162 exceptionIfMethodNotFound(methodName, mme3);
163 // drop the exception, there will be many
164 }
165 }
166 // dispatch to factories if it is not a literal method
167 return invokeFactoryMethod(methodName, arguments, mme2)
168 }
169 // }
170 }
171
172 Object invokeStaticMethod(Object object, String methodName, Object[] arguments) {
173 try {
174 if (object instanceof Class) {
175 return doInvokeInstanceMethod(object, methodName, arguments)
176 } else {
177 return doInvokeStaticMethod(object, methodName, arguments)
178 }
179 } catch (MissingMethodException mme) {
180 exceptionIfMethodNotFound(methodName, mme);
181 try {
182 return delegate.invokeMethod(object, methodName, arguments)
183 } catch (MissingMethodException mme2) {
184 exceptionIfMethodNotFound(methodName, mme2);
185
186 // attempt method resolution
187 for (UberBuilderRegistration reg in factory.builderRegistration) {
188 try {
189 def builder = reg.builder
190 if (!builder.getMetaClass().respondsTo(builder, methodName).isEmpty()) {
191 return InvokerHelper.invokeMethod(builder, methodName, arguments)
192 }
193 } catch (MissingMethodException mme3) {
194 exceptionIfMethodNotFound(methodName, mme3);
195
196 // drop the exception, there will be many
197 }
198 }
199 // dispatch to factories if it is not a literal method
200 return invokeFactoryMethod(methodName, arguments, mme2)
201 }
202 }
203 }
204
205 Object getProperty(Object o, String s) {
206 try {
207 return super.getProperty(o, s)
208 } catch (MissingPropertyException mpe) {
209 return factory.getProperty(s)
210 }
211 }
212
213 void setProperty(Object o, String s, Object o1) {
214 try {
215 super.setProperty(o, s, o1)
216 } catch (MissingPropertyException mpe) {
217 factory.setProperty(s, o1)
218 }
219 }
220 }
|