1 /*
2 * Copyright (c) 1998-2004 The Jgroup Team.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16 *
17 */
18
19 package jgroup.relacs.gmi;
20
21 import java.io.Serializable;
22 import java.lang.reflect.Method;
23 import java.rmi.Remote;
24 import java.util.HashMap;
25 import java.util.Iterator;
26 import java.util.Map;
27
28 import org.apache.log4j.Logger;
29
30 /**
31 * Table mapping a method (represented by a hash of the method or by
32 * a <code>Method</code> object) to its <code>MethodDetails</code> object.
33 *
34 * The mapping from <code>Method</code> objects will only be populated
35 * on the client-side since those are only used there.
36 *
37 * @author Hein Meling
38 * @since Jgroup 3.0
39 */
40 public class MethodTable
41 implements Serializable, Iterable<MethodDetails>
42 {
43
44 private static final long serialVersionUID = -7706887009118848315L;
45
46 ////////////////////////////////////////////////////////////////////////////////////////////
47 // Logger
48 ////////////////////////////////////////////////////////////////////////////////////////////
49
50 /** Obtain logger for this class */
51 private static final Logger log = Logger.getLogger(MethodTable.class);
52
53
54 ////////////////////////////////////////////////////////////////////////////////////////////
55 // Fields
56 ////////////////////////////////////////////////////////////////////////////////////////////
57
58 /** Table of methods (mapping from hash value to method details object) */
59 private final Map<Long,MethodDetails> table = new HashMap<Long,MethodDetails>();
60
61 /** Table mapping from method to method details object (only client-side) */
62 private transient Map<Method,MethodDetails> methTable;
63
64
65 ////////////////////////////////////////////////////////////////////////////////////////////
66 // Constructor
67 ////////////////////////////////////////////////////////////////////////////////////////////
68
69 public MethodTable()
70 {
71 }
72
73
74 ////////////////////////////////////////////////////////////////////////////////////////////
75 // Methods
76 ////////////////////////////////////////////////////////////////////////////////////////////
77
78 /**
79 * Add remote methods implemented by the given server to this
80 * method table. All methods defined in a <code>Remote</code>
81 * interface will be added, and their associated invocation
82 * semantics details will be computed.
83 */
84 public void addMethods(Object server)
85 {
86 /*
87 * Find all the remote interfaces implemented by the given
88 * server object, and compute relevant method information.
89 */
90 Class serverClass = server.getClass();
91 Class[] interfaces = serverClass.getInterfaces();
92 for (int i = 0; i < interfaces.length; i++) {
93 if (Remote.class.isAssignableFrom(interfaces[i])) {
94 Method methods[] = interfaces[i].getMethods();
95 for (int j = 0; j < methods.length; j++) {
96 MethodDetails meth = new MethodDetails(methods[j], server);
97 table.put(meth.getHash(), meth);
98 if (log.isDebugEnabled())
99 log.debug("Adding: " + meth);
100 }
101 }
102 }
103 }
104
105 /**
106 * Get the method details associated with the given hash value.
107 */
108 public MethodDetails get(long hash)
109 {
110 return table.get(hash);
111 }
112
113 /**
114 * Return the method details object associated with the given method.
115 */
116 public MethodDetails get(Method m)
117 {
118 if (methTable == null) {
119 methTable = new HashMap<Method,MethodDetails>();
120 }
121 MethodDetails method = methTable.get(m);
122 if (method == null) {
123 long hash = MethodDetails.computeHash(m);
124 method = get(hash);
125 methTable.put(m, method);
126 }
127 return method;
128 }
129
130
131 ////////////////////////////////////////////////////////////////////////////////////////////
132 // Methods from Iterable<MethodDetails>
133 ////////////////////////////////////////////////////////////////////////////////////////////
134
135 public Iterator<MethodDetails> iterator()
136 {
137 return table.values().iterator();
138 }
139
140
141 ////////////////////////////////////////////////////////////////////////////////////////////
142 // Object methods
143 ////////////////////////////////////////////////////////////////////////////////////////////
144
145 public String toString()
146 {
147 StringBuilder buf = new StringBuilder("MethodTable[");
148 for (Map.Entry<Long,MethodDetails> entry : table.entrySet()) {
149 MethodDetails meth = entry.getValue();
150 buf.append("\n");
151 buf.append(entry.getKey());
152 buf.append(" -> ");
153 buf.append(meth);
154 Object server = meth.getServer();
155 if (server != null) {
156 // the server object is only available on the server-side
157 buf.append("; server=");
158 buf.append(server.getClass().getSimpleName());
159 }
160 }
161 buf.append("]");
162 return buf.toString();
163 }
164
165 } // END MethodTable