Clover Coverage Report - JmDNS 3.4.1
Coverage timestamp: Thu Aug 25 2011 13:06:33 CEST
295   541   50   14.05
52   425   0.17   10.5
21     2.38  
2    
 
  JmDNSTest       Line # 41 287 0% 45 37 89.6% 0.89635855
  JmDNSTest.Receive       Line # 404 8 0% 5 0 100% 1.0
 
  (17)
 
1    package javax.jmdns.test;
2   
3    import static junit.framework.Assert.assertEquals;
4    import static junit.framework.Assert.assertTrue;
5    import static junit.framework.Assert.*;
6    import static org.easymock.EasyMock.capture;
7    import static org.easymock.EasyMock.createMock;
8    import static org.easymock.EasyMock.createNiceMock;
9    import static org.easymock.EasyMock.replay;
10    import static org.easymock.EasyMock.verify;
11   
12    import java.io.IOException;
13    import java.net.DatagramPacket;
14    import java.net.InetAddress;
15    import java.net.Inet6Address;
16    import java.net.MulticastSocket;
17    import java.net.NetworkInterface;
18    import java.net.UnknownHostException;
19    import java.util.Enumeration;
20    import java.util.HashMap;
21    import java.util.Map;
22    import java.util.logging.ConsoleHandler;
23    import java.util.logging.Level;
24    import java.util.logging.LogManager;
25    import java.util.logging.Logger;
26   
27    import javax.jmdns.JmDNS;
28    import javax.jmdns.ServiceEvent;
29    import javax.jmdns.ServiceInfo;
30    import javax.jmdns.ServiceListener;
31    import javax.jmdns.ServiceTypeListener;
32    import javax.jmdns.impl.constants.DNSConstants;
33   
34    import junit.framework.Assert;
35   
36    import org.easymock.Capture;
37    import org.easymock.EasyMock;
38    import org.junit.Before;
39    import org.junit.Test;
40   
 
41    public class JmDNSTest {
42   
43    @SuppressWarnings("unused")
44    private ServiceTypeListener typeListenerMock;
45    private ServiceListener serviceListenerMock;
46    private ServiceInfo service;
47   
48    private final static String serviceKey = "srvname"; // Max 9 chars
49   
 
50  17 toggle @Before
51    public void setup() {
52  17 boolean log = false;
53  17 if (log) {
54  0 ConsoleHandler handler = new ConsoleHandler();
55  0 handler.setLevel(Level.FINEST);
56  0 for (Enumeration<String> enumerator = LogManager.getLogManager().getLoggerNames(); enumerator.hasMoreElements();) {
57  0 String loggerName = enumerator.nextElement();
58  0 Logger logger = Logger.getLogger(loggerName);
59  0 logger.addHandler(handler);
60  0 logger.setLevel(Level.FINEST);
61    }
62    }
63   
64  17 String text = "Test hypothetical web server";
65  17 Map<String, byte[]> properties = new HashMap<String, byte[]>();
66  17 properties.put(serviceKey, text.getBytes());
67  17 service = ServiceInfo.create("_html._tcp.local.", "apache-someuniqueid", 80, 0, 0, true, properties);
68  17 typeListenerMock = createMock(ServiceTypeListener.class);
69  17 serviceListenerMock = createNiceMock("ServiceListener", ServiceListener.class);
70    }
71   
 
72  1 toggle @Test
73    public void testCreate() throws IOException {
74  1 System.out.println("Unit Test: testCreate()");
75  1 JmDNS registry = JmDNS.create();
76  1 registry.close();
77    }
78   
 
79  1 toggle @Test
80    public void testCreateINet() throws IOException {
81  1 System.out.println("Unit Test: testCreateINet()");
82  1 JmDNS registry = JmDNS.create(InetAddress.getLocalHost());
83    // assertEquals("We did not register on the local host inet:", InetAddress.getLocalHost(), registry.getInterface());
84  1 registry.close();
85    }
86   
 
87  1 toggle @Test
88    public void testRegisterService() throws IOException {
89  1 System.out.println("Unit Test: testRegisterService()");
90  1 JmDNS registry = null;
91  1 try {
92  1 registry = JmDNS.create();
93  1 registry.registerService(service);
94    } finally {
95  1 if (registry != null) registry.close();
96    }
97    }
98   
 
99  1 toggle @Test
100    public void testUnregisterService() throws IOException, InterruptedException {
101  1 System.out.println("Unit Test: testUnregisterService()");
102  1 JmDNS registry = null;
103  1 try {
104  1 registry = JmDNS.create();
105  1 registry.registerService(service);
106   
107  1 ServiceInfo[] services = registry.list(service.getType());
108  1 assertEquals("We should see the service we just registered: ", 1, services.length);
109  1 assertEquals(service, services[0]);
110   
111    // now unregister and make sure it's gone
112  1 registry.unregisterService(services[0]);
113   
114    // According to the spec the record disappears from the cache 1s after it has been unregistered
115    // without sleeping for a while, the service would not be unregistered fully
116  1 Thread.sleep(1500);
117   
118  1 services = registry.list(service.getType());
119  1 assertTrue("We should not see the service we just unregistered: ", services == null || services.length == 0);
120    } finally {
121  1 if (registry != null) registry.close();
122    }
123    }
124   
 
125  1 toggle @Test
126    public void testRegisterServiceTwice() throws IOException {
127  1 System.out.println("Unit Test: testRegisterService()");
128  1 JmDNS registry = null;
129  1 try {
130  1 registry = JmDNS.create();
131  1 registry.registerService(service);
132    // This should cause an exception
133  1 registry.registerService(service);
134  0 fail("Registering the same service info should fail.");
135    } catch (IllegalStateException exception) {
136    // Expected exception.
137    } finally {
138  1 if (registry != null) registry.close();
139    }
140    }
141   
 
142  1 toggle @Test
143    public void testUnregisterAndReregisterService() throws IOException, InterruptedException {
144  1 System.out.println("Unit Test: testUnregisterAndReregisterService()");
145  1 JmDNS registry = null;
146  1 try {
147  1 registry = JmDNS.create();
148  1 registry.registerService(service);
149   
150  1 ServiceInfo[] services = registry.list(service.getType());
151  1 assertEquals("We should see the service we just registered: ", 1, services.length);
152  1 assertEquals(service, services[0]);
153   
154    // now unregister and make sure it's gone
155  1 registry.unregisterService(services[0]);
156   
157    // According to the spec the record disappears from the cache 1s after it has been unregistered
158    // without sleeping for a while, the service would not be unregistered fully
159  1 Thread.sleep(1500);
160   
161  1 services = registry.list(service.getType());
162  1 assertTrue("We should not see the service we just unregistered: ", services == null || services.length == 0);
163   
164  1 registry.registerService(service);
165  1 Thread.sleep(5000);
166  1 services = registry.list(service.getType());
167  1 assertTrue("We should see the service we just reregistered: ", services != null && services.length > 0);
168    } finally {
169  1 if (registry != null) registry.close();
170    }
171    }
172   
 
173  1 toggle @Test
174    public void testQueryMyService() throws IOException {
175  1 System.out.println("Unit Test: testQueryMyService()");
176  1 JmDNS registry = null;
177  1 try {
178  1 registry = JmDNS.create();
179  1 registry.registerService(service);
180  1 ServiceInfo queriedService = registry.getServiceInfo(service.getType(), service.getName());
181  1 assertEquals(service, queriedService);
182    } finally {
183  1 if (registry != null) registry.close();
184    }
185    }
186   
 
187  1 toggle @Test
188    public void testListMyService() throws IOException {
189  1 System.out.println("Unit Test: testListMyService()");
190  1 JmDNS registry = null;
191  1 try {
192  1 registry = JmDNS.create();
193  1 registry.registerService(service);
194  1 ServiceInfo[] services = registry.list(service.getType());
195  1 assertEquals("We should see the service we just registered: ", 1, services.length);
196  1 assertEquals(service, services[0]);
197    } finally {
198  1 if (registry != null) registry.close();
199    }
200    }
201   
 
202  1 toggle @Test
203    public void testListMyServiceIPV6() throws IOException {
204  1 System.out.println("Unit Test: testListMyServiceIPV6()");
205  1 JmDNS registry = null;
206  1 try {
207  1 InetAddress address = InetAddress.getLocalHost();
208  1 NetworkInterface interfaze = NetworkInterface.getByInetAddress(address);
209  3 for (Enumeration<InetAddress> iaenum = interfaze.getInetAddresses(); iaenum.hasMoreElements();) {
210  2 InetAddress interfaceAddress = iaenum.nextElement();
211  2 if (interfaceAddress instanceof Inet6Address) {
212  1 address = interfaceAddress;
213    }
214    }
215  1 registry = JmDNS.create(address);
216  1 registry.registerService(service);
217  1 ServiceInfo[] services = registry.list(service.getType());
218  1 assertEquals("We should see the service we just registered: ", 1, services.length);
219  1 assertEquals(service, services[0]);
220    } finally {
221  1 if (registry != null) registry.close();
222    }
223    }
224   
 
225  1 toggle @Test
226    public void testListenForMyService() throws IOException {
227  1 System.out.println("Unit Test: testListenForMyService()");
228  1 JmDNS registry = null;
229  1 try {
230  1 Capture<ServiceEvent> capServiceAddedEvent = new Capture<ServiceEvent>();
231  1 Capture<ServiceEvent> capServiceResolvedEvent = new Capture<ServiceEvent>();
232    // Add an expectation that the listener interface will be called once capture the object so I can verify it separately.
233  1 serviceListenerMock.serviceAdded(capture(capServiceAddedEvent));
234  1 serviceListenerMock.serviceResolved(capture(capServiceResolvedEvent));
235  1 EasyMock.replay(serviceListenerMock);
236    // EasyMock.makeThreadSafe(serviceListenerMock, false);
237   
238  1 registry = JmDNS.create();
239   
240  1 registry.addServiceListener(service.getType(), serviceListenerMock);
241   
242  1 registry.registerService(service);
243   
244    // We get the service added event when we register the service. However the service has not been resolved at this point.
245    // The info associated with the event only has the minimum information i.e. name and type.
246  1 assertTrue("We did not get the service added event.", capServiceAddedEvent.hasCaptured());
247  1 ServiceInfo info = capServiceAddedEvent.getValue().getInfo();
248  1 assertEquals("We did not get the right name for the added service:", service.getName(), info.getName());
249  1 assertEquals("We did not get the right type for the added service:", service.getType(), info.getType());
250  1 assertEquals("We did not get the right fully qualified name for the added service:", service.getQualifiedName(), info.getQualifiedName());
251   
252    // assertEquals("We should not get the server for the added service:", "", info.getServer());
253    // assertEquals("We should not get the address for the added service:", null, info.getAddress());
254    // assertEquals("We should not get the HostAddress for the added service:", "", info.getHostAddress());
255    // assertEquals("We should not get the InetAddress for the added service:", null, info.getInetAddress());
256    // assertEquals("We should not get the NiceTextString for the added service:", "", info.getNiceTextString());
257    // assertEquals("We should not get the Priority for the added service:", 0, info.getPriority());
258    // assertFalse("We should not get the PropertyNames for the added service:", info.getPropertyNames().hasMoreElements());
259    // assertEquals("We should not get the TextBytes for the added service:", 0, info.getTextBytes().length);
260    // assertEquals("We should not get the TextString for the added service:", null, info.getTextString());
261    // assertEquals("We should not get the Weight for the added service:", 0, info.getWeight());
262    // assertNotSame("We should not get the URL for the added service:", "", info.getURL());
263   
264  1 registry.requestServiceInfo(service.getType(), service.getName());
265   
266  1 assertTrue("We did not get the service resolved event.", capServiceResolvedEvent.hasCaptured());
267  1 verify(serviceListenerMock);
268  1 ServiceInfo resolvedInfo = capServiceResolvedEvent.getValue().getInfo();
269  1 assertEquals("Did not get the expected service info: ", service, resolvedInfo);
270    } finally {
271  1 if (registry != null) registry.close();
272    }
273    }
274   
 
275  1 toggle @Test
276    public void testListenForMyServiceAndList() throws IOException {
277  1 System.out.println("Unit Test: testListenForMyServiceAndList()");
278  1 JmDNS registry = null;
279  1 try {
280  1 Capture<ServiceEvent> capServiceAddedEvent = new Capture<ServiceEvent>();
281  1 Capture<ServiceEvent> capServiceResolvedEvent = new Capture<ServiceEvent>();
282    // Expect the listener to be called once and capture the result
283  1 serviceListenerMock.serviceAdded(capture(capServiceAddedEvent));
284  1 serviceListenerMock.serviceResolved(capture(capServiceResolvedEvent));
285  1 replay(serviceListenerMock);
286   
287  1 registry = JmDNS.create();
288  1 registry.addServiceListener(service.getType(), serviceListenerMock);
289  1 registry.registerService(service);
290   
291    // We get the service added event when we register the service. However the service has not been resolved at this point.
292    // The info associated with the event only has the minimum information i.e. name and type.
293  1 assertTrue("We did not get the service added event.", capServiceAddedEvent.hasCaptured());
294   
295  1 ServiceInfo info = capServiceAddedEvent.getValue().getInfo();
296  1 assertEquals("We did not get the right name for the resolved service:", service.getName(), info.getName());
297  1 assertEquals("We did not get the right type for the resolved service:", service.getType(), info.getType());
298   
299    // This will force the resolution of the service which in turn will get the listener called with a service resolved event.
300    // The info associated with a service resolved event has all the information available.
301    // Which in turn populates the ServiceInfo opbjects returned by JmDNS.list.
302  1 ServiceInfo[] services = registry.list(info.getType());
303  1 assertEquals("We did not get the expected number of services: ", 1, services.length);
304  1 assertEquals("The service returned was not the one expected", service, services[0]);
305   
306  1 assertTrue("We did not get the service resolved event.", capServiceResolvedEvent.hasCaptured());
307  1 verify(serviceListenerMock);
308  1 ServiceInfo resolvedInfo = capServiceResolvedEvent.getValue().getInfo();
309  1 assertEquals("Did not get the expected service info: ", service, resolvedInfo);
310    } finally {
311  1 if (registry != null) registry.close();
312    }
313    }
314   
 
315  1 toggle @Test
316    public void testListenForServiceOnOtherRegistry() throws IOException {
317  1 System.out.println("Unit Test: testListenForServiceOnOtherRegistry()");
318  1 JmDNS registry = null;
319  1 JmDNS newServiceRegistry = null;
320  1 try {
321  1 Capture<ServiceEvent> capServiceAddedEvent = new Capture<ServiceEvent>();
322  1 Capture<ServiceEvent> capServiceResolvedEvent = new Capture<ServiceEvent>();
323    // Expect the listener to be called once and capture the result
324  1 serviceListenerMock.serviceAdded(capture(capServiceAddedEvent));
325  1 serviceListenerMock.serviceResolved(capture(capServiceResolvedEvent));
326  1 replay(serviceListenerMock);
327   
328  1 registry = JmDNS.create();
329  1 registry.addServiceListener(service.getType(), serviceListenerMock);
330    //
331  1 newServiceRegistry = JmDNS.create();
332  1 newServiceRegistry.registerService(service);
333   
334    // We get the service added event when we register the service. However the service has not been resolved at this point.
335    // The info associated with the event only has the minimum information i.e. name and type.
336  1 assertTrue("We did not get the service added event.", capServiceAddedEvent.hasCaptured());
337  1 ServiceInfo info = capServiceAddedEvent.getValue().getInfo();
338  1 assertEquals("We did not get the right name for the resolved service:", service.getName(), info.getName());
339  1 assertEquals("We did not get the right type for the resolved service:", service.getType(), info.getType());
340    // We get the service added event when we register the service. However the service has not been resolved at this point.
341    // The info associated with the event only has the minimum information i.e. name and type.
342  1 assertTrue("We did not get the service resolved event.", capServiceResolvedEvent.hasCaptured());
343  1 verify(serviceListenerMock);
344  1 Object result = capServiceResolvedEvent.getValue().getInfo();
345  1 assertEquals("Did not get the expected service info: ", service, result);
346    } finally {
347  1 if (registry != null) registry.close();
348  1 if (newServiceRegistry != null) newServiceRegistry.close();
349    }
350    }
351   
 
352  1 toggle @Test
353    public void testWaitAndQueryForServiceOnOtherRegistry() throws IOException {
354  1 System.out.println("Unit Test: testWaitAndQueryForServiceOnOtherRegistry()");
355  1 JmDNS registry = null;
356  1 JmDNS newServiceRegistry = null;
357  1 try {
358  1 newServiceRegistry = JmDNS.create();
359  1 registry = JmDNS.create();
360   
361  1 registry.registerService(service);
362   
363  1 ServiceInfo fetchedService = newServiceRegistry.getServiceInfo(service.getType(), service.getName());
364   
365  1 assertEquals("Did not get the expected service info: ", service, fetchedService);
366    } finally {
367  1 if (registry != null) registry.close();
368  1 if (newServiceRegistry != null) newServiceRegistry.close();
369    }
370    }
371   
 
372  1 toggle @Test
373    public void testRegisterAndListServiceOnOtherRegistry() throws IOException, InterruptedException {
374  1 System.out.println("Unit Test: testRegisterAndListServiceOnOtherRegistry()");
375  1 JmDNS registry = null;
376  1 JmDNS newServiceRegistry = null;
377  1 try {
378  1 registry = JmDNS.create("Registry");
379  1 registry.registerService(service);
380   
381  1 newServiceRegistry = JmDNS.create("Listener");
382  1 Thread.sleep(6000);
383  1 ServiceInfo[] fetchedServices = newServiceRegistry.list(service.getType());
384  1 assertEquals("Did not get the expected services listed:", 1, fetchedServices.length);
385  1 assertEquals("Did not get the expected service type:", service.getType(), fetchedServices[0].getType());
386  1 assertEquals("Did not get the expected service name:", service.getName(), fetchedServices[0].getName());
387  1 assertEquals("Did not get the expected service fully qualified name:", service.getQualifiedName(), fetchedServices[0].getQualifiedName());
388  1 newServiceRegistry.getServiceInfo(service.getType(), service.getName());
389   
390  1 assertEquals("Did not get the expected service info: ", service, fetchedServices[0]);
391  1 registry.close();
392  1 registry = null;
393    // According to the spec the record disappears from the cache 1s after it has been unregistered
394    // without sleeping for a while, the service would not be unregistered fully
395  1 Thread.sleep(1500);
396  1 fetchedServices = newServiceRegistry.list(service.getType());
397  1 assertEquals("The service was not cancelled after the close:", 0, fetchedServices.length);
398    } finally {
399  1 if (registry != null) registry.close();
400  1 if (newServiceRegistry != null) newServiceRegistry.close();
401    }
402    }
403   
 
404    public static final class Receive extends Thread {
405    MulticastSocket _socket;
406    DatagramPacket _in;
407   
 
408  3 toggle public Receive(MulticastSocket socket, DatagramPacket in) {
409  3 super("Test Receive Multicast");
410  3 _socket = socket;
411  3 _in = in;
412    }
413   
 
414  3 toggle @Override
415    public void run() {
416  3 try {
417  3 _socket.receive(_in);
418    } catch (IOException exception) {
419    // Ignore
420    }
421    }
422   
 
423  3 toggle public boolean waitForReceive() {
424  3 try {
425  3 this.join(1000);
426    } catch (InterruptedException exception) {
427    // Ignore
428    }
429  3 return this.isAlive();
430    }
431   
432    }
433   
434    private final static int MPORT = 8053;
435   
 
436  1 toggle @Test
437    public void testTwoMulticastPortsAtOnce() throws UnknownHostException, IOException {
438  1 System.out.println("Unit Test: testTwoMulticastPortsAtOnce()");
439  1 MulticastSocket firstSocket = null;
440  1 MulticastSocket secondSocket = null;
441  1 try {
442  1 String firstMessage = "ping";
443  1 String secondMessage = "pong";
444  1 InetAddress someInet = InetAddress.getByName(DNSConstants.MDNS_GROUP);
445  1 firstSocket = new MulticastSocket(MPORT);
446  1 secondSocket = new MulticastSocket(MPORT);
447   
448  1 firstSocket.joinGroup(someInet);
449  1 secondSocket.joinGroup(someInet);
450    //
451  1 DatagramPacket out = new DatagramPacket(firstMessage.getBytes("UTF-8"), firstMessage.length(), someInet, MPORT);
452  1 DatagramPacket inFirst = new DatagramPacket(firstMessage.getBytes("UTF-8"), firstMessage.length(), someInet, MPORT);
453  1 DatagramPacket inSecond = new DatagramPacket(firstMessage.getBytes("UTF-8"), firstMessage.length(), someInet, MPORT);
454  1 Receive receiveSecond = new Receive(secondSocket, inSecond);
455  1 receiveSecond.start();
456  1 Receive receiveFirst = new Receive(firstSocket, inSecond);
457  1 receiveFirst.start();
458  1 firstSocket.send(out);
459  1 if (receiveSecond.waitForReceive()) {
460  0 Assert.fail("We did not receive the data in the second socket");
461    }
462  1 String fromFirst = new String(inSecond.getData(), "UTF-8");
463  1 assertEquals("Expected the second socket to recieve the same message the first socket sent", firstMessage, fromFirst);
464    // Make sure the first socket had read its own message
465  1 if (receiveSecond.waitForReceive()) {
466  0 Assert.fail("We did not receive the data in the first socket");
467    }
468    // Reverse the roles
469  1 out = new DatagramPacket(secondMessage.getBytes("UTF-8"), secondMessage.length(), someInet, MPORT);
470  1 inFirst = new DatagramPacket(secondMessage.getBytes("UTF-8"), secondMessage.length(), someInet, MPORT);
471  1 receiveFirst = new Receive(firstSocket, inSecond);
472  1 receiveFirst.start();
473   
474  1 secondSocket.send(out);
475  1 if (receiveFirst.waitForReceive()) {
476  0 Assert.fail("We did not receive the data in the first socket");
477    }
478  1 String fromSecond = new String(inFirst.getData(), "UTF-8");
479  1 assertEquals("Expected the first socket to recieve the same message the second socket sent", secondMessage, fromSecond);
480    } finally {
481  1 if (firstSocket != null) firstSocket.close();
482  1 if (secondSocket != null) secondSocket.close();
483    }
484    }
485   
 
486  1 toggle @Test
487    public void testListMyServiceWithToLowerCase() throws IOException, InterruptedException {
488  1 System.out.println("Unit Test: testListMyServiceWithToLowerCase()");
489  1 String text = "Test hypothetical web server";
490  1 Map<String, byte[]> properties = new HashMap<String, byte[]>();
491  1 properties.put(serviceKey, text.getBytes());
492  1 service = ServiceInfo.create("_HtmL._TcP.lOcAl.", "apache-someUniqueid", 80, 0, 0, true, properties);
493  1 JmDNS registry = null;
494  1 try {
495  1 registry = JmDNS.create();
496  1 registry.registerService(service);
497   
498    // with toLowerCase
499  1 ServiceInfo[] services = registry.list(service.getType().toLowerCase());
500  1 assertEquals("We should see the service we just registered: ", 1, services.length);
501  1 assertEquals(service, services[0]);
502    // now unregister and make sure it's gone
503  1 registry.unregisterService(services[0]);
504    // According to the spec the record disappears from the cache 1s after it has been unregistered
505    // without sleeping for a while, the service would not be unregistered fully
506  1 Thread.sleep(1500);
507  1 services = registry.list(service.getType().toLowerCase());
508  1 assertTrue("We should not see the service we just unregistered: ", services == null || services.length == 0);
509    } finally {
510  1 if (registry != null) registry.close();
511    }
512    }
513   
 
514  1 toggle @Test
515    public void testListMyServiceWithoutLowerCase() throws IOException, InterruptedException {
516  1 System.out.println("Unit Test: testListMyServiceWithoutLowerCase()");
517  1 String text = "Test hypothetical web server";
518  1 Map<String, byte[]> properties = new HashMap<String, byte[]>();
519  1 properties.put(serviceKey, text.getBytes());
520  1 service = ServiceInfo.create("_HtmL._TcP.lOcAl.", "apache-someUniqueid", 80, 0, 0, true, properties);
521  1 JmDNS registry = null;
522  1 try {
523  1 registry = JmDNS.create();
524  1 registry.registerService(service);
525   
526    // without toLowerCase
527  1 ServiceInfo[] services = registry.list(service.getType());
528  1 assertEquals("We should see the service we just registered: ", 1, services.length);
529  1 assertEquals(service, services[0]);
530    // now unregister and make sure it's gone
531  1 registry.unregisterService(services[0]);
532    // According to the spec the record disappears from the cache 1s after it has been unregistered
533    // without sleeping for a while, the service would not be unregistered fully
534  1 Thread.sleep(1500);
535  1 services = registry.list(service.getType());
536  1 assertTrue("We should not see the service we just unregistered: ", services == null || services.length == 0);
537    } finally {
538  1 if (registry != null) registry.close();
539    }
540    }
541    }