1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package jgroup.relacs.gmi;
19
20 import java.io.Externalizable;
21 import java.io.IOException;
22 import java.io.ObjectInput;
23 import java.io.ObjectInputStream;
24 import java.io.ObjectOutput;
25 import java.io.ObjectOutputStream;
26 import java.io.OutputStream;
27 import java.lang.reflect.Method;
28 import java.lang.reflect.Proxy;
29 import java.rmi.RemoteException;
30
31 import jgroup.core.GroupManager;
32 import jgroup.core.IID;
33 import jgroup.core.JgroupException;
34 import jgroup.core.ExternalGMIService.BootstrapInvocationHandler;
35 import jgroup.relacs.gm.TimestampService;
36 import jgroup.relacs.gm.TimestampService.Timestamp;
37 import jgroup.relacs.rmi.IIDFactory;
38 import jgroup.util.log.Eventlogger;
39 import net.jini.jeri.ObjectEndpoint;
40 import net.jini.jeri.OutboundRequest;
41 import net.jini.jeri.OutboundRequestIterator;
42
43 import org.apache.log4j.Logger;
44
45 import com.sun.jini.jeri.internal.runtime.Util;
46
47
48
49
50
51
52
53
54
55 public class GroupInvocationHandler
56 implements BootstrapInvocationHandler, Externalizable
57 {
58
59
60
61
62
63
64 private static final Logger log = Logger.getLogger(GroupInvocationHandler.class);
65
66
67
68
69
70
71 private static final long serialVersionUID = 6090074369501693886L;
72
73
74 public static final String TYPE = "GroupInvocationHandler";
75
76
77
78
79
80
81
82 private GroupEndPoint gep;
83
84
85 private MethodTable methodTable;
86
87
88 private IIDFactory generator;
89
90
91 private long clientViewId = -1;
92
93
94 private TimestampService timestampService;
95
96
97
98
99
100
101
102
103
104 public GroupInvocationHandler() {}
105
106
107
108
109
110
111
112 public GroupInvocationHandler(ObjectEndpoint oe, MethodTable methodTable)
113 {
114 this.gep = (GroupEndPoint) oe;
115 this.methodTable = methodTable;
116 generator = new IIDFactory();
117 }
118
119
120
121
122
123
124
125
126
127 public Object invoke(Object proxy, Method method, Object[] args)
128 throws Exception
129 {
130 if (method.getDeclaringClass() == Object.class) {
131 return invokeObjectMethod(proxy, method, args);
132 } else
133 return invokeRemoteMethod(proxy, method, args);
134 }
135
136
137
138
139
140
141
142
143
144 private Object invokeObjectMethod(Object proxy, Method method, Object[] args)
145 {
146 String name = method.getName();
147
148 if (name.equals("hashCode")) {
149 return new Integer(hashCode());
150 } else if (name.equals("equals")) {
151 Object obj = args[0];
152 boolean b = (proxy == obj) ||
153 ((obj != null) && Util.sameProxyClass(proxy, obj) &&
154 equals(Proxy.getInvocationHandler(obj)));
155 return Boolean.valueOf(b);
156 } else if (name.equals("toString")) {
157 return proxyToString(proxy);
158 } else {
159 throw new IllegalArgumentException("Unexpected object method: " + method);
160 }
161 }
162
163
164
165
166
167 public int hashCode()
168 {
169 return gep.hashCode();
170 }
171
172
173
174
175
176
177 private String proxyToString(Object proxy)
178 {
179 Class[] interfaces = proxy.getClass().getInterfaces();
180
181 if (interfaces.length == 0) {
182 return "Proxy[" + this + "]";
183 }
184 String iface = interfaces[0].getName();
185 int dot = iface.lastIndexOf('.');
186
187 if (dot >= 0) {
188 iface = iface.substring(dot + 1);
189 }
190 return "Proxy[" + iface + "," + gep + "]";
191 }
192
193
194
195
196
197 private Object invokeRemoteMethod(Object proxy, Method method, Object[] args)
198 throws Exception
199 {
200 IID iid = generator.getId();
201 MethodDetails info = methodTable.get(method);
202 boolean invoked = false;
203 InvocationResult result = null;
204
205 do {
206
207 OutboundRequestIterator iter = gep.newCall(info.getInvocationSemantics());
208 while (result == null && iter.hasNext()) {
209 try {
210 result = invokeRequest(iid, info, args, iter.next());
211 } catch (IOException ioex) {
212
213
214
215
216
217 if (Eventlogger.ENABLED)
218 Eventlogger.logEvent("FailureDetected");
219 if (log.isDebugEnabled())
220 log.debug("IOException caught", ioex);
221 }
222 }
223
224 if (result != null)
225 invoked = true;
226 } while (!invoked);
227 gep.updateClientView(result.getServerView());
228 clientViewId = result.getServerViewId();
229
230 generator.addReply(iid);
231 return result.getResult();
232 }
233
234
235
236
237
238
239
240
241
242 protected InvocationResult invokeRequest(IID iid, MethodDetails minfo, Object[] args, OutboundRequest req)
243 throws IOException, JgroupException
244 {
245 if (log.isDebugEnabled())
246 log.debug("Invoking: " + minfo + " with iid=" + iid);
247
248 OutputStream os = req.getRequestOutputStream();
249
250
251
252
253 os.write(minfo.getInvocationSemantics().ordinal());
254
255
256
257
258
259
260
261 ObjectOutputStream out = new ObjectOutputStream(os);
262
263 out.writeObject(iid);
264
265
266 if (timestampService != null) {
267 synchronized (timestampService) {
268
269 Timestamp ts = timestampService.getTimestamp(gep.getGroupId());
270 if (log.isDebugEnabled())
271 log.debug("GroupInvocationHandler.invoke ts = " + ts + " on " + minfo);
272 out.writeObject(ts);
273 }
274 } else {
275 out.writeObject(null);
276 }
277
278 out.writeLong(clientViewId);
279
280 out.writeLong(minfo.getHash());
281
282 for (int i = 0; args != null && i < args.length; ++i)
283 out.writeObject(args[i]);
284 out.flush();
285 out.close();
286
287 if (log.isDebugEnabled())
288 log.debug("Data sent for " + minfo);
289
290
291 RemoteException remex = gep.executeCall(req);
292 if (remex != null)
293 throw remex;
294
295
296 ObjectInputStream in = new ObjectInputStream(req.getResponseInputStream());
297 if (log.isDebugEnabled())
298 log.debug("Result received for " + minfo);
299 try {
300 return (InvocationResult) in.readObject();
301 } catch (ClassNotFoundException cnfex) {
302 throw new JgroupException("Returned class could not be deserialized!", cnfex);
303 }
304 }
305
306
307 public GroupEndPoint getGroupEndPoint()
308 {
309 return gep;
310 }
311
312
313
314
315
316
317
318
319
320 public void setGroupManager(GroupManager gm)
321 {
322 timestampService = (TimestampService) gm.getService(TimestampService.class);
323 }
324
325
326
327
328
329
330
331
332
333 public void readExternal(ObjectInput in)
334 throws IOException, ClassNotFoundException
335 {
336 gep = new GroupEndPoint();
337 gep.readExternal(in);
338 methodTable = (MethodTable) in.readObject();
339 generator = new IIDFactory();
340 }
341
342
343
344
345 public void writeExternal(ObjectOutput out)
346 throws IOException
347 {
348 gep.writeExternal(out);
349 out.writeObject(methodTable);
350 }
351
352
353
354
355
356
357 public String getType()
358 {
359 return TYPE;
360 }
361
362 public void merge(BootstrapInvocationHandler handler)
363 throws JgroupException, RemoteException
364 {
365 if (!handler.getType().equals(TYPE))
366 throw new JgroupException("Incompatible type: " + handler.getType());
367 GroupInvocationHandler h = (GroupInvocationHandler) handler;
368 gep.addMembers(h.gep.getMembers());
369 }
370
371 }