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