KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > logicalcobwebs > proxool > proxy > MethodMapper


1 /*
2  * This software is released under a licence similar to the Apache Software Licence.
3  * See org.logicalcobwebs.proxool.package.html for details.
4  * The latest version is available at http://proxool.sourceforge.net
5  */

6 package org.logicalcobwebs.proxool.proxy;
7
8 import org.logicalcobwebs.proxool.ProxoolException;
9
10 import java.lang.reflect.Method JavaDoc;
11 import java.util.Map JavaDoc;
12 import java.util.HashMap JavaDoc;
13
14 /**
15  * Handles the mapping between methods with identical signatures but that are not related
16  * by inheritance. This allows you to invoke a method on a class using an interface that
17  * it doesn't actually implement. It caches the result of its reflective lookup to save time.
18  * If the concreteClass does in fact implement the injectable interface then it quickly
19  * returns the method without the penalty of mapping using reflection.
20  *
21  * @author <a HREF="mailto:bill@logicalcobwebs.co.uk">Bill Horsman</a>
22  * @author $Author: billhorsman $ (current maintainer)
23  * @version $Revision: 1.2 $, $Date: 2004/07/13 21:06:18 $
24  * @since Proxool 0.9
25  */

26 public class MethodMapper {
27
28     private Class JavaDoc concreteClass;
29
30     private Map JavaDoc cachedConcreteMethods = new HashMap JavaDoc();
31     ;
32     /**
33      * @param concreteClass the class that we want to invoke methods on. It should either implement all methods on
34      * the injectable interface, or provide methods with an identical signature.
35      */

36     public MethodMapper(Class JavaDoc concreteClass) {
37         this.concreteClass = concreteClass;
38     }
39
40     /**
41      * Returns the method in the concrete class with an indentical signature to that passed
42      * as a parameter
43      *
44      * @param injectableMethod provides signature that we are trying to match
45      * @return the method in the concrete class that we can invoke as if it were in the interface
46      * @throws org.logicalcobwebs.proxool.ProxoolException
47      * if the method is not found.
48      */

49     protected Method JavaDoc getConcreteMethod(Method JavaDoc injectableMethod) throws ProxoolException {
50         // Do we have a cached reference?
51
Method JavaDoc concreteMethod = (Method JavaDoc) cachedConcreteMethods.get(injectableMethod);
52         if (concreteMethod == null) {
53             // Look it up
54
Method JavaDoc[] candidateMethods = concreteClass.getMethods();
55             for (int i = 0; i < candidateMethods.length; i++) {
56                 Method JavaDoc candidateMethod = candidateMethods[i];
57                 // First pass: does the name, parameter count and return type match?
58
if (candidateMethod.getName().equals(injectableMethod.getName()) &&
59                         candidateMethod.getParameterTypes().length == injectableMethod.getParameterTypes().length &&
60                         candidateMethod.getReturnType().equals(injectableMethod.getReturnType())) {
61                     // Let's check each parameter type
62
boolean matches = true;
63                     Class JavaDoc[] candidateTypes = candidateMethod.getParameterTypes();
64                     Class JavaDoc[] injectableTypes = injectableMethod.getParameterTypes();
65                     for (int j = 0; j < candidateTypes.length; j++) {
66                         if (!candidateTypes[j].equals(injectableTypes[j])) {
67                             matches = false;
68                             break;
69                         }
70
71                     }
72                     if (matches) {
73                         concreteMethod = candidateMethod;
74                         break;
75                     }
76                 }
77             }
78             // Success?
79
if (concreteMethod == null) {
80                 throw new ProxoolException("Couldn't match injectable method " + injectableMethod + " with any of those " +
81                         "found in " + concreteClass.getName());
82             }
83             // Remember it
84
cachedConcreteMethods.put(injectableMethod, concreteMethod);
85         }
86         return concreteMethod;
87     }
88
89     /**
90      * Don't use the one we calculate using {@link #getConcreteMethod(java.lang.reflect.Method)}, use this one instead.
91      * @param injectableMethod the method supplied by the proxy
92      * @param overridenMethod the one we are going to use (probably the same as injectrableMethod actually)
93      */

94     public void overrideConcreteMethod(Method JavaDoc injectableMethod, Method JavaDoc overridenMethod) {
95         cachedConcreteMethods.put(injectableMethod, overridenMethod);
96     }
97
98 }
99
100 /*
101  Revision history:
102  $Log: MethodMapper.java,v $
103  Revision 1.2 2004/07/13 21:06:18 billhorsman
104  Fix problem using injectable interfaces on methods that are declared in non-public classes.
105
106  Revision 1.1 2004/06/02 20:43:53 billhorsman
107  New classes to support injectable interfaces
108
109 */
Popular Tags