1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.remoting.rmi;
18
19 import java.rmi.AlreadyBoundException;
20 import java.rmi.NoSuchObjectException;
21 import java.rmi.NotBoundException;
22 import java.rmi.Remote;
23 import java.rmi.RemoteException;
24 import java.rmi.registry.LocateRegistry;
25 import java.rmi.registry.Registry;
26 import java.rmi.server.RMIClientSocketFactory;
27 import java.rmi.server.RMIServerSocketFactory;
28 import java.rmi.server.UnicastRemoteObject;
29
30 import org.springframework.beans.factory.DisposableBean;
31 import org.springframework.beans.factory.InitializingBean;
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69 public class RmiServiceExporter extends RmiBasedExporter implements InitializingBean, DisposableBean {
70
71 private String serviceName;
72
73 private int servicePort = 0;
74
75 private RMIClientSocketFactory clientSocketFactory;
76
77 private RMIServerSocketFactory serverSocketFactory;
78
79 private Registry registry;
80
81 private String registryHost;
82
83 private int registryPort = Registry.REGISTRY_PORT;
84
85 private RMIClientSocketFactory registryClientSocketFactory;
86
87 private RMIServerSocketFactory registryServerSocketFactory;
88
89 private boolean alwaysCreateRegistry = false;
90
91 private boolean replaceExistingBinding = true;
92
93 private Remote exportedObject;
94
95 private boolean createdRegistry = false;
96
97
98
99
100
101
102 public void setServiceName(String serviceName) {
103 this.serviceName = serviceName;
104 }
105
106
107
108
109
110 public void setServicePort(int servicePort) {
111 this.servicePort = servicePort;
112 }
113
114
115
116
117
118
119
120
121
122
123 public void setClientSocketFactory(RMIClientSocketFactory clientSocketFactory) {
124 this.clientSocketFactory = clientSocketFactory;
125 }
126
127
128
129
130
131
132
133
134
135
136 public void setServerSocketFactory(RMIServerSocketFactory serverSocketFactory) {
137 this.serverSocketFactory = serverSocketFactory;
138 }
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154 public void setRegistry(Registry registry) {
155 this.registry = registry;
156 }
157
158
159
160
161
162
163 public void setRegistryHost(String registryHost) {
164 this.registryHost = registryHost;
165 }
166
167
168
169
170
171
172
173 public void setRegistryPort(int registryPort) {
174 this.registryPort = registryPort;
175 }
176
177
178
179
180
181
182
183
184
185
186 public void setRegistryClientSocketFactory(RMIClientSocketFactory registryClientSocketFactory) {
187 this.registryClientSocketFactory = registryClientSocketFactory;
188 }
189
190
191
192
193
194
195
196
197
198
199 public void setRegistryServerSocketFactory(RMIServerSocketFactory registryServerSocketFactory) {
200 this.registryServerSocketFactory = registryServerSocketFactory;
201 }
202
203
204
205
206
207
208
209
210 public void setAlwaysCreateRegistry(boolean alwaysCreateRegistry) {
211 this.alwaysCreateRegistry = alwaysCreateRegistry;
212 }
213
214
215
216
217
218
219
220
221
222
223 public void setReplaceExistingBinding(boolean replaceExistingBinding) {
224 this.replaceExistingBinding = replaceExistingBinding;
225 }
226
227
228 @Override
229 public void afterPropertiesSet() throws RemoteException {
230 prepare();
231 }
232
233
234
235
236
237
238 public void prepare() throws RemoteException {
239 checkService();
240
241 if (this.serviceName == null) {
242 throw new IllegalArgumentException("Property 'serviceName' is required");
243 }
244
245
246 if (this.clientSocketFactory instanceof RMIServerSocketFactory) {
247 this.serverSocketFactory = (RMIServerSocketFactory) this.clientSocketFactory;
248 }
249 if ((this.clientSocketFactory != null && this.serverSocketFactory == null) ||
250 (this.clientSocketFactory == null && this.serverSocketFactory != null)) {
251 throw new IllegalArgumentException(
252 "Both RMIClientSocketFactory and RMIServerSocketFactory or none required");
253 }
254
255
256 if (this.registryClientSocketFactory instanceof RMIServerSocketFactory) {
257 this.registryServerSocketFactory = (RMIServerSocketFactory) this.registryClientSocketFactory;
258 }
259 if (this.registryClientSocketFactory == null && this.registryServerSocketFactory != null) {
260 throw new IllegalArgumentException(
261 "RMIServerSocketFactory without RMIClientSocketFactory for registry not supported");
262 }
263
264 this.createdRegistry = false;
265
266
267 if (this.registry == null) {
268 this.registry = getRegistry(this.registryHost, this.registryPort,
269 this.registryClientSocketFactory, this.registryServerSocketFactory);
270 this.createdRegistry = true;
271 }
272
273
274 this.exportedObject = getObjectToExport();
275
276 if (logger.isInfoEnabled()) {
277 logger.info("Binding service '" + this.serviceName + "' to RMI registry: " + this.registry);
278 }
279
280
281 if (this.clientSocketFactory != null) {
282 UnicastRemoteObject.exportObject(
283 this.exportedObject, this.servicePort, this.clientSocketFactory, this.serverSocketFactory);
284 }
285 else {
286 UnicastRemoteObject.exportObject(this.exportedObject, this.servicePort);
287 }
288
289
290 try {
291 if (this.replaceExistingBinding) {
292 this.registry.rebind(this.serviceName, this.exportedObject);
293 }
294 else {
295 this.registry.bind(this.serviceName, this.exportedObject);
296 }
297 }
298 catch (AlreadyBoundException ex) {
299
300 unexportObjectSilently();
301 throw new IllegalStateException(
302 "Already an RMI object bound for name '" + this.serviceName + "': " + ex.toString());
303 }
304 catch (RemoteException ex) {
305
306 unexportObjectSilently();
307 throw ex;
308 }
309 }
310
311
312
313
314
315
316
317
318
319
320
321
322 protected Registry getRegistry(String registryHost, int registryPort,
323 RMIClientSocketFactory clientSocketFactory, RMIServerSocketFactory serverSocketFactory)
324 throws RemoteException {
325
326 if (registryHost != null) {
327
328 if (logger.isInfoEnabled()) {
329 logger.info("Looking for RMI registry at port '" + registryPort + "' of host [" + registryHost + "]");
330 }
331 Registry reg = LocateRegistry.getRegistry(registryHost, registryPort, clientSocketFactory);
332 testRegistry(reg);
333 return reg;
334 }
335
336 else {
337 return getRegistry(registryPort, clientSocketFactory, serverSocketFactory);
338 }
339 }
340
341
342
343
344
345
346
347
348
349 protected Registry getRegistry(
350 int registryPort, RMIClientSocketFactory clientSocketFactory, RMIServerSocketFactory serverSocketFactory)
351 throws RemoteException {
352
353 if (clientSocketFactory != null) {
354 if (this.alwaysCreateRegistry) {
355 logger.info("Creating new RMI registry");
356 return LocateRegistry.createRegistry(registryPort, clientSocketFactory, serverSocketFactory);
357 }
358 if (logger.isInfoEnabled()) {
359 logger.info("Looking for RMI registry at port '" + registryPort + "', using custom socket factory");
360 }
361 synchronized (LocateRegistry.class) {
362 try {
363
364 Registry reg = LocateRegistry.getRegistry(null, registryPort, clientSocketFactory);
365 testRegistry(reg);
366 return reg;
367 }
368 catch (RemoteException ex) {
369 logger.debug("RMI registry access threw exception", ex);
370 logger.info("Could not detect RMI registry - creating new one");
371
372 return LocateRegistry.createRegistry(registryPort, clientSocketFactory, serverSocketFactory);
373 }
374 }
375 }
376
377 else {
378 return getRegistry(registryPort);
379 }
380 }
381
382
383
384
385
386
387
388 protected Registry getRegistry(int registryPort) throws RemoteException {
389 if (this.alwaysCreateRegistry) {
390 logger.info("Creating new RMI registry");
391 return LocateRegistry.createRegistry(registryPort);
392 }
393 if (logger.isInfoEnabled()) {
394 logger.info("Looking for RMI registry at port '" + registryPort + "'");
395 }
396 synchronized (LocateRegistry.class) {
397 try {
398
399 Registry reg = LocateRegistry.getRegistry(registryPort);
400 testRegistry(reg);
401 return reg;
402 }
403 catch (RemoteException ex) {
404 logger.debug("RMI registry access threw exception", ex);
405 logger.info("Could not detect RMI registry - creating new one");
406
407 return LocateRegistry.createRegistry(registryPort);
408 }
409 }
410 }
411
412
413
414
415
416
417
418
419
420 protected void testRegistry(Registry registry) throws RemoteException {
421 registry.list();
422 }
423
424
425
426
427
428 @Override
429 public void destroy() throws RemoteException {
430 if (logger.isInfoEnabled()) {
431 logger.info("Unbinding RMI service '" + this.serviceName +
432 "' from registry" + (this.createdRegistry ? (" at port '" + this.registryPort + "'") : ""));
433 }
434 try {
435 this.registry.unbind(this.serviceName);
436 }
437 catch (NotBoundException ex) {
438 if (logger.isWarnEnabled()) {
439 logger.warn("RMI service '" + this.serviceName + "' is not bound to registry"
440 + (this.createdRegistry ? (" at port '" + this.registryPort + "' anymore") : ""), ex);
441 }
442 }
443 finally {
444 unexportObjectSilently();
445 }
446 }
447
448
449
450
451 private void unexportObjectSilently() {
452 try {
453 UnicastRemoteObject.unexportObject(this.exportedObject, true);
454 }
455 catch (NoSuchObjectException ex) {
456 if (logger.isWarnEnabled()) {
457 logger.warn("RMI object for service '" + this.serviceName + "' isn't exported anymore", ex);
458 }
459 }
460 }
461 }