KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > geronimo > kernel > basic > ProxyMethodInterceptor


1 /**
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17 package org.apache.geronimo.kernel.basic;
18
19 import net.sf.cglib.asm.Type;
20 import net.sf.cglib.core.Signature;
21 import net.sf.cglib.proxy.MethodInterceptor;
22 import net.sf.cglib.proxy.MethodProxy;
23 import net.sf.cglib.reflect.FastClass;
24 import org.apache.geronimo.gbean.AbstractName;
25 import org.apache.geronimo.gbean.GAttributeInfo;
26 import org.apache.geronimo.gbean.GBeanData;
27 import org.apache.geronimo.gbean.GBeanInfo;
28 import org.apache.geronimo.gbean.GOperationInfo;
29 import org.apache.geronimo.gbean.GOperationSignature;
30 import org.apache.geronimo.gbean.runtime.GBeanInstance;
31 import org.apache.geronimo.gbean.runtime.RawInvoker;
32 import org.apache.geronimo.kernel.Kernel;
33 import org.apache.geronimo.kernel.management.State;
34 import org.apache.geronimo.kernel.proxy.DeadProxyException;
35 import org.apache.geronimo.kernel.proxy.GeronimoManagedBean;
36
37 import java.beans.Introspector JavaDoc;
38 import java.lang.reflect.Method JavaDoc;
39 import java.util.HashSet JavaDoc;
40 import java.util.Iterator JavaDoc;
41 import java.util.Map JavaDoc;
42 import java.util.Set JavaDoc;
43
44 /**
45  * @version $Rev: 476049 $ $Date: 2006-11-16 23:35:17 -0500 (Thu, 16 Nov 2006) $
46  */

47 public class ProxyMethodInterceptor implements MethodInterceptor {
48     /**
49      * Type of the proxy interface
50      */

51     private final Class JavaDoc proxyType;
52
53     /**
54      * The object name to which we are connected.
55      */

56     private final AbstractName abstractName;
57
58     /**
59      * GBeanInvokers keyed on the proxy interface method index
60      */

61     private ProxyInvoker[] gbeanInvokers;
62
63     public ProxyMethodInterceptor(Class JavaDoc proxyType, Kernel kernel, AbstractName abstractName) {
64         assert proxyType != null;
65         assert kernel != null;
66         assert abstractName != null;
67
68         this.proxyType = proxyType;
69         this.abstractName = abstractName;
70         gbeanInvokers = createGBeanInvokers(kernel, abstractName);
71     }
72
73     public synchronized void destroy() {
74         gbeanInvokers = null;
75     }
76
77     public AbstractName getAbstractName() {
78         return abstractName;
79     }
80
81     public final Object JavaDoc intercept(final Object JavaDoc object, final Method JavaDoc method, final Object JavaDoc[] args, final MethodProxy proxy) throws Throwable JavaDoc {
82         ProxyInvoker gbeanInvoker;
83
84         int interfaceIndex = proxy.getSuperIndex();
85         synchronized (this) {
86             if (gbeanInvokers == null) {
87                 throw new DeadProxyException("Proxy is no longer valid");
88             }
89             gbeanInvoker = gbeanInvokers[interfaceIndex];
90         }
91
92         if (gbeanInvoker == null) {
93             throw new UnsupportedOperationException JavaDoc("No implementation method: objectName=" + abstractName + ", method=" + method);
94         }
95
96         return gbeanInvoker.invoke(abstractName, args);
97     }
98
99     private ProxyInvoker[] createGBeanInvokers(Kernel kernel, AbstractName abstractName) {
100         ProxyInvoker[] invokers;
101         try {
102             RawInvoker rawInvoker = (RawInvoker) kernel.getAttribute(abstractName, GBeanInstance.RAW_INVOKER);
103             invokers = createRawGBeanInvokers(rawInvoker, proxyType);
104         } catch (Exception JavaDoc e) {
105             invokers = createKernelGBeanInvokers(kernel, abstractName, proxyType);
106         }
107
108         // handle equals, hashCode and toString directly here
109
try {
110             invokers[getSuperIndex(proxyType, proxyType.getMethod("equals", new Class JavaDoc[]{Object JavaDoc.class}))] = new EqualsInvoke(kernel);
111             invokers[getSuperIndex(proxyType, proxyType.getMethod("hashCode", null))] = new HashCodeInvoke();
112             invokers[getSuperIndex(proxyType, proxyType.getMethod("toString", null))] = new ToStringInvoke(proxyType.getName());
113             if(GeronimoManagedBean.class.isAssignableFrom(proxyType)) {
114                 invokers[getSuperIndex(proxyType, proxyType.getMethod("getState", null))] = new GetStateInvoke(kernel);
115                 invokers[getSuperIndex(proxyType, proxyType.getMethod("getStateInstance", null))] = new GetStateInstanceInvoke(kernel);
116                 invokers[getSuperIndex(proxyType, proxyType.getMethod("start", null))] = new StartInvoke(kernel);
117                 invokers[getSuperIndex(proxyType, proxyType.getMethod("startRecursive", null))] = new StartRecursiveInvoke(kernel);
118                 invokers[getSuperIndex(proxyType, proxyType.getMethod("stop", null))] = new StopInvoke(kernel);
119                 invokers[getSuperIndex(proxyType, proxyType.getMethod("getStartTime", null))] = new GetStartTimeInvoke(kernel);
120                 invokers[getSuperIndex(proxyType, proxyType.getMethod("getObjectName", null))] = new GetObjectNameInvoke(kernel);
121             }
122         } catch (Exception JavaDoc e) {
123             // this can not happen... all classes must implement equals, hashCode and toString
124
throw new AssertionError JavaDoc(new Exception JavaDoc("Could not install invoker for proxyType " + proxyType + " for target " + abstractName, e));
125         }
126
127         return invokers;
128     }
129
130     private ProxyInvoker[] createRawGBeanInvokers(RawInvoker rawInvoker, Class JavaDoc proxyType) {
131         Map JavaDoc operations = rawInvoker.getOperationIndex();
132         Map JavaDoc attributes = rawInvoker.getAttributeIndex();
133
134         // build the method lookup table
135
FastClass fastClass = FastClass.create(proxyType);
136         ProxyInvoker[] invokers = new ProxyInvoker[fastClass.getMaxIndex() + 1];
137         Method JavaDoc[] methods = proxyType.getMethods();
138         for (int i = 0; i < methods.length; i++) {
139             Method JavaDoc method = methods[i];
140             int interfaceIndex = getSuperIndex(proxyType, method);
141             if (interfaceIndex >= 0) {
142                 invokers[interfaceIndex] = createRawGBeanInvoker(rawInvoker, method, operations, attributes);
143             }
144         }
145
146         return invokers;
147     }
148
149     private ProxyInvoker createRawGBeanInvoker(RawInvoker rawInvoker, Method JavaDoc method, Map JavaDoc operations, Map JavaDoc attributes) {
150         if (operations.containsKey(new GOperationSignature(method))) {
151             int methodIndex = ((Integer JavaDoc) operations.get(new GOperationSignature(method))).intValue();
152             return new RawOperationInvoker(rawInvoker, methodIndex);
153         }
154
155         if (method.getName().startsWith("get")) {
156             String JavaDoc attributeName = method.getName().substring(3);
157             Integer JavaDoc methodIndex = ((Integer JavaDoc) attributes.get(attributeName));
158             if (methodIndex != null) {
159                 return new RawGetAttributeInvoker(rawInvoker, methodIndex.intValue());
160             }
161             methodIndex = getMethodIndex(attributes, attributeName);
162             if (methodIndex != null) {
163                 return new RawGetAttributeInvoker(rawInvoker, methodIndex.intValue());
164             }
165         }
166
167         if (method.getName().startsWith("is")) {
168             String JavaDoc attributeName = method.getName().substring(2);
169             Integer JavaDoc methodIndex = ((Integer JavaDoc) attributes.get(attributeName));
170             if (methodIndex != null) {
171                 return new RawGetAttributeInvoker(rawInvoker, methodIndex.intValue());
172             }
173             methodIndex = getMethodIndex(attributes, attributeName);
174             if (methodIndex != null) {
175                 return new RawGetAttributeInvoker(rawInvoker, methodIndex.intValue());
176             }
177         }
178
179         if (method.getName().startsWith("set")) {
180             String JavaDoc attributeName = method.getName().substring(3);
181             Integer JavaDoc methodIndex = ((Integer JavaDoc) attributes.get(attributeName));
182             if (methodIndex != null) {
183                 return new RawSetAttributeInvoker(rawInvoker, methodIndex.intValue());
184             }
185             methodIndex = getMethodIndex(attributes, attributeName);
186             if (methodIndex != null) {
187                 return new RawSetAttributeInvoker(rawInvoker, methodIndex.intValue());
188             }
189         }
190         return null;
191     }
192
193     private ProxyInvoker[] createKernelGBeanInvokers(Kernel kernel, AbstractName abstractName, Class JavaDoc proxyType) {
194         GBeanInfo info;
195         try {
196             info = kernel.getGBeanInfo(abstractName);
197         } catch (Exception JavaDoc e) {
198             throw new IllegalArgumentException JavaDoc("Could not get GBeanInfo for target object: " + abstractName);
199         }
200
201         // build attributeName->attributeInfo map
202
Set JavaDoc attributeInfos = info.getAttributes();
203         Set JavaDoc attributeNames = new HashSet JavaDoc(attributeInfos.size());
204         for (Iterator JavaDoc iterator = attributeInfos.iterator(); iterator.hasNext();) {
205             GAttributeInfo attributeInfo = (GAttributeInfo) iterator.next();
206             attributeNames.add(attributeInfo.getName());
207         }
208
209         // build operationSignature->operationInfo map
210
Set JavaDoc operationInfos = info.getOperations();
211         Set JavaDoc operationSignatures = new HashSet JavaDoc(operationInfos.size());
212         for (Iterator JavaDoc iterator = operationInfos.iterator(); iterator.hasNext();) {
213             GOperationInfo operationInfo = (GOperationInfo) iterator.next();
214             operationSignatures.add(new GOperationSignature(operationInfo.getName(), operationInfo.getParameterList()));
215         }
216
217         // build the method lookup table
218
FastClass fastClass = FastClass.create(proxyType);
219         ProxyInvoker[] invokers = new ProxyInvoker[fastClass.getMaxIndex() + 1];
220         Method JavaDoc[] methods = proxyType.getMethods();
221         for (int i = 0; i < methods.length; i++) {
222             Method JavaDoc method = methods[i];
223             int interfaceIndex = getSuperIndex(proxyType, method);
224             if (interfaceIndex >= 0) {
225                 invokers[interfaceIndex] = createJMXGBeanInvoker(kernel, method, operationSignatures, attributeNames);
226             }
227         }
228
229         return invokers;
230     }
231
232     private ProxyInvoker createJMXGBeanInvoker(Kernel kernel, Method JavaDoc method, Set JavaDoc operationSignatures, Set JavaDoc attributeNames) {
233         if (operationSignatures.contains(new GOperationSignature(method))) {
234             return new KernelOperationInvoker(kernel, method);
235         }
236
237         String JavaDoc name = method.getName();
238         if (name.startsWith("get")) {
239             String JavaDoc attributeName = method.getName().substring(3);
240             if (attributeNames.contains(attributeName)) {
241                 return new KernelGetAttributeInvoker(kernel, attributeName);
242             }
243             attributeName = Introspector.decapitalize(attributeName);
244             if (attributeNames.contains(attributeName)) {
245                 return new KernelGetAttributeInvoker(kernel, attributeName);
246             }
247         } else if (name.startsWith("is")) {
248             String JavaDoc attrName = method.getName().substring(2);
249             if (attributeNames.contains(attrName)) {
250                 return new KernelGetAttributeInvoker(kernel, attrName);
251             }
252             attrName = Introspector.decapitalize(attrName);
253             if (attributeNames.contains(attrName)) {
254                 return new KernelGetAttributeInvoker(kernel, attrName);
255             }
256         } else if (name.startsWith("set")) {
257             String JavaDoc attrName = method.getName().substring(3);
258             if (attributeNames.contains(attrName)) {
259                 return new KernelSetAttributeInvoker(kernel, attrName);
260             }
261             attrName = Introspector.decapitalize(attrName);
262             if (attributeNames.contains(attrName)) {
263                 return new KernelSetAttributeInvoker(kernel, attrName);
264             }
265         }
266         return null;
267     }
268
269     private static int getSuperIndex(Class JavaDoc proxyType, Method JavaDoc method) {
270         Signature signature = new Signature(method.getName(), Type.getReturnType(method), Type.getArgumentTypes(method));
271         MethodProxy methodProxy = MethodProxy.find(proxyType, signature);
272         if (methodProxy != null) {
273             return methodProxy.getSuperIndex();
274         }
275         return -1;
276     }
277
278     private static Integer JavaDoc getMethodIndex(Map JavaDoc attributes, String JavaDoc attributeName) {
279         Iterator JavaDoc iter = attributes.keySet().iterator();
280         while (iter.hasNext()) {
281             String JavaDoc key = (String JavaDoc) iter.next();
282             if (key.equalsIgnoreCase(attributeName)) {
283                 return (Integer JavaDoc) attributes.get(key);
284             }
285         }
286         return null;
287     }
288
289     static final class HashCodeInvoke implements ProxyInvoker {
290         public Object JavaDoc invoke(AbstractName abstractName, Object JavaDoc[] arguments) throws Throwable JavaDoc {
291             return new Integer JavaDoc(abstractName.hashCode());
292         }
293     }
294
295     static final class EqualsInvoke implements ProxyInvoker {
296         private final Kernel kernel;
297
298         public EqualsInvoke(Kernel kernel) {
299             this.kernel = kernel;
300         }
301
302         public Object JavaDoc invoke(AbstractName abstractName, Object JavaDoc[] arguments) throws Throwable JavaDoc {
303             AbstractName proxyTarget = kernel.getAbstractNameFor(arguments[0]);
304             return Boolean.valueOf(abstractName.equals(proxyTarget));
305         }
306     }
307
308     static final class ToStringInvoke implements ProxyInvoker {
309         private final String JavaDoc interfaceName;
310
311         public ToStringInvoke(String JavaDoc interfaceName) {
312             this.interfaceName = "[" + interfaceName + ": ";
313         }
314
315         public Object JavaDoc invoke(AbstractName abstractName, Object JavaDoc[] arguments) throws Throwable JavaDoc {
316             return interfaceName + abstractName + "]";
317         }
318     }
319
320     static final class GetStateInvoke implements ProxyInvoker {
321         private Kernel kernel;
322
323         public GetStateInvoke(Kernel kernel) {
324             this.kernel = kernel;
325         }
326
327         public Object JavaDoc invoke(AbstractName abstractName, Object JavaDoc[] arguments) throws Throwable JavaDoc {
328             return new Integer JavaDoc(kernel.getGBeanState(abstractName));
329         }
330     }
331
332     static final class GetStateInstanceInvoke implements ProxyInvoker {
333         private Kernel kernel;
334
335         public GetStateInstanceInvoke(Kernel kernel) {
336             this.kernel = kernel;
337         }
338
339         public Object JavaDoc invoke(AbstractName abstractName, Object JavaDoc[] arguments) throws Throwable JavaDoc {
340             return State.fromInt(kernel.getGBeanState(abstractName));
341         }
342     }
343
344     static final class StartInvoke implements ProxyInvoker {
345         private Kernel kernel;
346
347         public StartInvoke(Kernel kernel) {
348             this.kernel = kernel;
349         }
350
351         public Object JavaDoc invoke(AbstractName abstractName, Object JavaDoc[] arguments) throws Throwable JavaDoc {
352             kernel.startGBean(abstractName);
353             return null;
354         }
355     }
356
357     static final class StartRecursiveInvoke implements ProxyInvoker {
358         private Kernel kernel;
359
360         public StartRecursiveInvoke(Kernel kernel) {
361             this.kernel = kernel;
362         }
363
364         public Object JavaDoc invoke(AbstractName abstractName, Object JavaDoc[] arguments) throws Throwable JavaDoc {
365             kernel.startRecursiveGBean(abstractName);
366             return null;
367         }
368     }
369
370     static final class GetStartTimeInvoke implements ProxyInvoker {
371         private Kernel kernel;
372
373         public GetStartTimeInvoke(Kernel kernel) {
374             this.kernel = kernel;
375         }
376
377         public Object JavaDoc invoke(AbstractName abstractName, Object JavaDoc[] arguments) throws Throwable JavaDoc {
378             return new Long JavaDoc(kernel.getGBeanStartTime(abstractName));
379         }
380     }
381
382     static final class StopInvoke implements ProxyInvoker {
383         private Kernel kernel;
384
385         public StopInvoke(Kernel kernel) {
386             this.kernel = kernel;
387         }
388
389         public Object JavaDoc invoke(AbstractName abstractName, Object JavaDoc[] arguments) throws Throwable JavaDoc {
390             kernel.stopGBean(abstractName);
391             return null;
392         }
393     }
394
395     static final class GetObjectNameInvoke implements ProxyInvoker {
396         private Kernel kernel;
397
398         public GetObjectNameInvoke(Kernel kernel) {
399             this.kernel = kernel;
400         }
401
402         public Object JavaDoc invoke(AbstractName abstractName, Object JavaDoc[] arguments) throws Throwable JavaDoc {
403             GBeanData gBeanData = kernel.getGBeanData(abstractName);
404             return gBeanData.getAbstractName().getObjectName().getCanonicalName();
405         }
406     }
407 }
408
Popular Tags