changeset 1358:f0750a42ef85

Convert RMIRegistry to an OSGi service This patch converts the RMIRegistry class used by the agent proxy into an OSGi service. This will allow all Thermostat agent bundles to easily share the same RMI registry, which is restricted to localhost only. The motivation for this patch is the future plan to add a proxy to system-backend to allow a special "thermostat" user to receive monitoring updates for other users' processes with jvmstat. Reviewed-by: omajid Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2013-November/008864.html
author Elliott Baron <ebaron@redhat.com>
date Fri, 22 Nov 2013 13:30:58 -0500
parents 3b8ba31730f7
children a397b66516f2
files agent/core/src/main/java/com/redhat/thermostat/agent/RMIRegistry.java agent/core/src/main/java/com/redhat/thermostat/agent/internal/Activator.java agent/core/src/main/java/com/redhat/thermostat/agent/internal/RMIRegistryImpl.java agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/AgentProxyClient.java agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/MXBeanConnectionPoolImpl.java agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/MXBeanConnector.java agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/RMIRegistry.java agent/core/src/test/java/com/redhat/thermostat/agent/internal/ActivatorTest.java agent/core/src/test/java/com/redhat/thermostat/agent/internal/RMIRegistryImplTest.java agent/core/src/test/java/com/redhat/thermostat/utils/management/internal/AgentProxyClientTest.java agent/core/src/test/java/com/redhat/thermostat/utils/management/internal/MXBeanConnectionPoolImplTest.java agent/core/src/test/java/com/redhat/thermostat/utils/management/internal/RMIRegistryTest.java
diffstat 12 files changed, 379 insertions(+), 252 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/main/java/com/redhat/thermostat/agent/RMIRegistry.java	Fri Nov 22 13:30:58 2013 -0500
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2012, 2013 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.registry.Registry;
+
+import com.redhat.thermostat.annotations.Service;
+
+/**
+ * Maintains an RMI registry used for inter-process communication between
+ * the Thermostat agent and other helper processes on the same host.
+ */
+@Service
+public interface RMIRegistry {
+
+    /**
+     * @return the underlying {@link Registry} maintained by this service.
+     * @throws RemoteException if this method fails to obtain the registry
+     */
+    Registry getRegistry() throws RemoteException;
+
+    /**
+     * Exports the provided remote object to the RMI registry.
+     * @param obj - the object to be exported
+     * @return a remote stub of the exported object
+     * @throws RemoteException if this method fails to export the object
+     */
+    Remote export(Remote obj) throws RemoteException;
+
+    /**
+     * Unexports a previously exported remote object from the RMI registry.
+     * @param obj - the object to be unexported
+     * @return whether the operation was successful
+     * @throws RemoteException if an error occurred trying to unexport 
+     * the object
+     */
+    boolean unexport(Remote obj) throws RemoteException;
+
+}
\ No newline at end of file
--- a/agent/core/src/main/java/com/redhat/thermostat/agent/internal/Activator.java	Fri Nov 22 13:28:33 2013 -0500
+++ b/agent/core/src/main/java/com/redhat/thermostat/agent/internal/Activator.java	Fri Nov 22 13:30:58 2013 -0500
@@ -40,8 +40,8 @@
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
 
+import com.redhat.thermostat.agent.RMIRegistry;
 import com.redhat.thermostat.agent.VmBlacklist;
-
 import com.redhat.thermostat.agent.config.AgentConfigsUtils;
 import com.redhat.thermostat.shared.config.CommonPaths;
 import com.redhat.thermostat.utils.management.MXBeanConnectionPool;
@@ -56,9 +56,11 @@
 
     @Override
     public void start(BundleContext context) throws Exception {
+        RMIRegistryImpl registry = new RMIRegistryImpl();
+        context.registerService(RMIRegistry.class, registry, null);
         ServiceReference<CommonPaths> pathsRef = context.getServiceReference(CommonPaths.class);
         CommonPaths paths = context.getService(pathsRef);
-        pool = new MXBeanConnectionPoolImpl(paths.getSystemBinRoot());
+        pool = new MXBeanConnectionPoolImpl(registry, paths.getSystemBinRoot());
         context.registerService(MXBeanConnectionPool.class, pool, null);
         AgentConfigsUtils.setConfigFiles(paths.getSystemAgentConfigurationFile(), paths.getUserAgentConfigurationFile(),
         		                   paths.getUserAgentAuthConfigFile());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/main/java/com/redhat/thermostat/agent/internal/RMIRegistryImpl.java	Fri Nov 22 13:30:58 2013 -0500
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2012, 2013 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent.internal;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.rmi.NoSuchObjectException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.rmi.server.RMIClientSocketFactory;
+import java.rmi.server.RMIServerSocketFactory;
+import java.rmi.server.RMISocketFactory;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.logging.Logger;
+
+import com.redhat.thermostat.agent.RMIRegistry;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+
+public class RMIRegistryImpl implements RMIRegistry {
+    
+    private static final Logger logger = LoggingUtils.getLogger(RMIRegistryImpl.class);
+
+    private RegistryWrapper registryWrapper;
+    private ServerSocketCreator serverSockCreator;
+    private Registry registry;
+    
+    public RMIRegistryImpl() {
+        this(new RegistryWrapper(), new ServerSocketCreator());
+    }
+    
+    RMIRegistryImpl(RegistryWrapper registryWrapper, ServerSocketCreator serverSockCreator) {
+        this.registryWrapper = registryWrapper;
+        this.serverSockCreator = serverSockCreator;
+    }
+    
+    public void start() throws RemoteException {
+        this.registry = registryWrapper.createRegistry(Registry.REGISTRY_PORT /* TODO customize */,
+                RMISocketFactory.getDefaultSocketFactory(),
+                new RMIServerSocketFactory() {
+                    
+                    @Override
+                    public ServerSocket createServerSocket(int port) throws IOException {
+                        // Allow only local connections
+                        return serverSockCreator.createSocket(port, 0, InetAddress.getLoopbackAddress());
+                    }
+                });
+        logger.fine("Starting RMI registry");
+    }
+    
+    @Override
+    public Registry getRegistry() throws RemoteException {
+        // We get a class loading problem when returning the local registry reference,
+        // this returns a remote stub reference instead
+        return registryWrapper.getRegistry();
+    }
+    
+    public void stop() throws RemoteException {
+        if (registry != null) {
+            registryWrapper.destroyRegistry(registry);
+            registry = null;
+            logger.fine("Shutting down RMI registry");
+        }
+    }
+    
+    @Override
+    public Remote export(Remote obj) throws RemoteException {
+        if (registry == null) {
+            throw new RemoteException("RMI registry is not running");
+        }
+        return registryWrapper.export(obj, 0);
+    }
+    
+    @Override
+    public boolean unexport(Remote obj) throws RemoteException {
+        if (registry == null) {
+            throw new RemoteException("RMI registry is not running");
+        }
+        return registryWrapper.unexport(obj, true);
+    }
+    
+    /*
+     * For testing purposes only.
+     */
+    Registry getRegistryImpl() {
+        return registry;
+    }
+    
+    static class RegistryWrapper {
+        Registry createRegistry(int port, RMIClientSocketFactory csf,
+                RMIServerSocketFactory ssf) throws RemoteException {
+            return LocateRegistry.createRegistry(port, csf, ssf);
+        }
+        
+        Registry getRegistry() throws RemoteException {
+            return LocateRegistry.getRegistry(InetAddress.getLoopbackAddress().getHostName());
+        }
+        
+        void destroyRegistry(Registry registry) throws NoSuchObjectException {
+            // Shuts down RMI registry
+            UnicastRemoteObject.unexportObject(registry, true);
+        }
+        
+        Remote export(Remote obj, int port) throws RemoteException {
+            return UnicastRemoteObject.exportObject(obj, 0);
+        }
+        
+        boolean unexport(Remote obj, boolean force) throws NoSuchObjectException {
+            return UnicastRemoteObject.unexportObject(obj, force);
+        }
+    }
+    
+    static class ServerSocketCreator {
+        ServerSocket createSocket(int port, int backlog, InetAddress bindAddr) throws IOException {
+            return new ServerSocket(port, backlog, bindAddr);
+        }
+    }
+
+}
--- a/agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/AgentProxyClient.java	Fri Nov 22 13:28:33 2013 -0500
+++ b/agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/AgentProxyClient.java	Fri Nov 22 13:30:58 2013 -0500
@@ -45,6 +45,7 @@
 import java.util.concurrent.TimeUnit;
 import java.util.logging.Logger;
 
+import com.redhat.thermostat.agent.RMIRegistry;
 import com.redhat.thermostat.agent.proxy.common.AgentProxyControl;
 import com.redhat.thermostat.agent.proxy.common.AgentProxyListener;
 import com.redhat.thermostat.agent.proxy.common.AgentProxyLogin;
--- a/agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/MXBeanConnectionPoolImpl.java	Fri Nov 22 13:28:33 2013 -0500
+++ b/agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/MXBeanConnectionPoolImpl.java	Fri Nov 22 13:30:58 2013 -0500
@@ -44,6 +44,8 @@
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import com.redhat.thermostat.agent.RMIRegistry;
+import com.redhat.thermostat.agent.internal.RMIRegistryImpl;
 import com.redhat.thermostat.common.Pair;
 import com.redhat.thermostat.common.tools.ApplicationException;
 import com.redhat.thermostat.common.utils.LoggingUtils;
@@ -58,19 +60,14 @@
     private Map<Integer, Pair<Integer, MXBeanConnectionImpl>> pool = new HashMap<>();
 
     private final ConnectorCreator creator;
-    private final RMIRegistry registry;
+    private final RMIRegistryImpl registry;
     private final File binPath;
 
-    public MXBeanConnectionPoolImpl(File binPath) {
-        this(new ConnectorCreator(), new RMIRegistry(), binPath);
-    }
-    
-    // For testing purposes only
-    public MXBeanConnectionPoolImpl(RMIRegistry registry, File binPath) {
+    public MXBeanConnectionPoolImpl(RMIRegistryImpl registry, File binPath) {
         this(new ConnectorCreator(), registry, binPath);
     }
 
-    MXBeanConnectionPoolImpl(ConnectorCreator connectorCreator, RMIRegistry registry, File binPath) {
+    MXBeanConnectionPoolImpl(ConnectorCreator connectorCreator, RMIRegistryImpl registry, File binPath) {
         this.creator = connectorCreator;
         this.registry = registry;
         this.binPath = binPath;
--- a/agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/MXBeanConnector.java	Fri Nov 22 13:28:33 2013 -0500
+++ b/agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/MXBeanConnector.java	Fri Nov 22 13:30:58 2013 -0500
@@ -46,6 +46,7 @@
 import javax.management.remote.JMXConnectorFactory;
 import javax.management.remote.JMXServiceURL;
 
+import com.redhat.thermostat.agent.RMIRegistry;
 import com.redhat.thermostat.common.tools.ApplicationException;
 
 class MXBeanConnector implements Closeable {
--- a/agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/RMIRegistry.java	Fri Nov 22 13:28:33 2013 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,143 +0,0 @@
-/*
- * Copyright 2012, 2013 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.utils.management.internal;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.ServerSocket;
-import java.rmi.NoSuchObjectException;
-import java.rmi.Remote;
-import java.rmi.RemoteException;
-import java.rmi.registry.LocateRegistry;
-import java.rmi.registry.Registry;
-import java.rmi.server.RMIClientSocketFactory;
-import java.rmi.server.RMIServerSocketFactory;
-import java.rmi.server.RMISocketFactory;
-import java.rmi.server.UnicastRemoteObject;
-import java.util.logging.Logger;
-
-import com.redhat.thermostat.common.utils.LoggingUtils;
-
-public class RMIRegistry {
-    
-    private static final Logger logger = LoggingUtils.getLogger(RMIRegistry.class);
-
-    private RegistryCreator registryCreator;
-    private ServerSocketCreator serverSockCreator;
-    private Registry registry;
-    
-    public RMIRegistry() {
-        this(new RegistryCreator(), new ServerSocketCreator());
-    }
-    
-    RMIRegistry(RegistryCreator registryCreator, ServerSocketCreator serverSockCreator) {
-        this.registryCreator = registryCreator;
-        this.serverSockCreator = serverSockCreator;
-    }
-    
-    public void start() throws RemoteException {
-        this.registry = registryCreator.createRegistry(Registry.REGISTRY_PORT /* TODO customize */,
-                RMISocketFactory.getDefaultSocketFactory(),
-                new RMIServerSocketFactory() {
-                    
-                    @Override
-                    public ServerSocket createServerSocket(int port) throws IOException {
-                        // Allow only local connections
-                        return serverSockCreator.createSocket(port, 0, InetAddress.getLoopbackAddress());
-                    }
-                });
-        logger.fine("Starting RMI registry");
-    }
-    
-    public Registry getRegistry() throws RemoteException {
-        // We get a class loading problem when returning the local registry reference,
-        // this returns a remote stub reference instead
-        return registryCreator.getRegistry();
-    }
-    
-    public void stop() throws RemoteException {
-        if (registry != null) {
-            registryCreator.destroyRegistry(registry);
-            registry = null;
-            logger.fine("Shutting down RMI registry");
-        }
-    }
-    
-    public Remote export(Remote obj) throws RemoteException {
-        if (registry == null) {
-            throw new RemoteException("RMI registry is not running");
-        }
-        return UnicastRemoteObject.exportObject(obj, 0);
-    }
-    
-    public void unexport(Remote obj) throws RemoteException {
-        if (registry == null) {
-            throw new RemoteException("RMI registry is not running");
-        }
-        UnicastRemoteObject.unexportObject(obj, true);
-    }
-    
-    /*
-     * For testing purposes only.
-     */
-    Registry getRegistryImpl() {
-        return registry;
-    }
-    
-    static class RegistryCreator {
-        Registry createRegistry(int port, RMIClientSocketFactory csf,
-                RMIServerSocketFactory ssf) throws RemoteException {
-            return LocateRegistry.createRegistry(port, csf, ssf);
-        }
-        
-        Registry getRegistry() throws RemoteException {
-            return LocateRegistry.getRegistry(InetAddress.getLoopbackAddress().getHostName());
-        }
-        
-        void destroyRegistry(Registry registry) throws NoSuchObjectException {
-            // Shuts down RMI registry
-            UnicastRemoteObject.unexportObject(registry, true);
-        }
-    }
-    
-    static class ServerSocketCreator {
-        ServerSocket createSocket(int port, int backlog, InetAddress bindAddr) throws IOException {
-            return new ServerSocket(port, backlog, bindAddr);
-        }
-    }
-
-}
--- a/agent/core/src/test/java/com/redhat/thermostat/agent/internal/ActivatorTest.java	Fri Nov 22 13:28:33 2013 -0500
+++ b/agent/core/src/test/java/com/redhat/thermostat/agent/internal/ActivatorTest.java	Fri Nov 22 13:30:58 2013 -0500
@@ -45,6 +45,7 @@
 
 import org.junit.Test;
 
+import com.redhat.thermostat.agent.RMIRegistry;
 import com.redhat.thermostat.agent.VmBlacklist;
 import com.redhat.thermostat.shared.config.CommonPaths;
 import com.redhat.thermostat.shared.config.NativeLibraryResolver;
@@ -71,6 +72,7 @@
 
         activator.start(context);
 
+        assertTrue(context.isServiceRegistered(RMIRegistry.class.getName(), RMIRegistryImpl.class));
         assertTrue(context.isServiceRegistered(MXBeanConnectionPool.class.getName(), MXBeanConnectionPoolImpl.class));
         assertTrue(context.isServiceRegistered(UserNameUtil.class.getName(), UserNameUtilImpl.class));
         assertTrue(context.isServiceRegistered(VmBlacklist.class.getName(), VmBlacklistImpl.class));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/test/java/com/redhat/thermostat/agent/internal/RMIRegistryImplTest.java	Fri Nov 22 13:30:58 2013 -0500
@@ -0,0 +1,123 @@
+package com.redhat.thermostat.agent.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.registry.Registry;
+import java.rmi.server.RMIClientSocketFactory;
+import java.rmi.server.RMIServerSocketFactory;
+import java.rmi.server.RMISocketFactory;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import com.redhat.thermostat.agent.internal.RMIRegistryImpl.RegistryWrapper;
+import com.redhat.thermostat.agent.internal.RMIRegistryImpl.ServerSocketCreator;
+
+public class RMIRegistryImplTest {
+    
+    private RegistryWrapper wrapper;
+    private Registry reg;
+    private RMIRegistryImpl registry;
+    private ServerSocketCreator sockCreator;
+    
+    @Before
+    public void setup() throws RemoteException {
+        wrapper = mock(RegistryWrapper.class);
+        reg = mock(Registry.class);
+        when(wrapper.createRegistry(anyInt(), any(RMIClientSocketFactory.class), 
+                any(RMIServerSocketFactory.class))).thenReturn(reg);
+        sockCreator = mock(ServerSocketCreator.class);
+        
+        registry = new RMIRegistryImpl(wrapper, sockCreator);
+    }
+
+    @Test
+    public void testRegistryStart() throws IOException {
+        registry.start();
+        
+        ArgumentCaptor<Integer> portCaptor = ArgumentCaptor.forClass(Integer.class);
+        ArgumentCaptor<RMIClientSocketFactory> csfCaptor = ArgumentCaptor.forClass(RMIClientSocketFactory.class);
+        ArgumentCaptor<RMIServerSocketFactory> ssfCaptor = ArgumentCaptor.forClass(RMIServerSocketFactory.class);
+        verify(wrapper).createRegistry(portCaptor.capture(), csfCaptor.capture(), ssfCaptor.capture());
+        
+        // Ensure defaults used for port and client socket factory
+        int port = portCaptor.getValue();
+        assertEquals(Registry.REGISTRY_PORT, port);
+        
+        RMIClientSocketFactory csf = csfCaptor.getValue();
+        assertEquals(RMISocketFactory.getDefaultSocketFactory(), csf);
+        
+        // Ensure bound to loopback address
+        RMIServerSocketFactory ssf = ssfCaptor.getValue();
+        ssf.createServerSocket(port);
+        verify(sockCreator).createSocket(port, 0, InetAddress.getLoopbackAddress());
+    }
+
+    @Test
+    public void testRegistryStop() throws IOException {
+        registry.start();
+        
+        registry.stop();
+        
+        verify(wrapper).destroyRegistry(reg);
+        assertNull(registry.getRegistryImpl());
+    }
+    
+    @Test
+    public void testRegistryStopNotStarted() throws IOException {
+        registry.stop();
+        
+        verify(wrapper, never()).destroyRegistry(reg);
+    }
+    
+    @Test
+    public void testGetRegistry() throws Exception {
+        Registry stub = mock(Registry.class);
+        when(wrapper.getRegistry()).thenReturn(stub);
+        assertEquals(stub, registry.getRegistry());
+    }
+    
+    @Test
+    public void testExportObject() throws Exception {
+        Remote obj = mock(Remote.class);
+        Remote stub = mock(Remote.class);
+        when(wrapper.export(obj, 0)).thenReturn(stub);
+        
+        registry.start();
+        assertEquals(stub, registry.export(obj));
+    }
+    
+    @Test(expected=RemoteException.class)
+    public void testExportObjectNotStarted() throws Exception {
+        Remote obj = mock(Remote.class);
+        registry.export(obj);
+    }
+    
+    @Test
+    public void testUnexportObject() throws Exception {
+        Remote obj = mock(Remote.class);
+        when(wrapper.unexport(obj, true)).thenReturn(true);
+        
+        registry.start();
+        assertEquals(true, registry.unexport(obj));
+        verify(wrapper).unexport(obj, true);
+    }
+    
+    @Test(expected=RemoteException.class)
+    public void testUnexportObjectNotStarted() throws Exception {
+        Remote obj = mock(Remote.class);
+        registry.unexport(obj);
+    }
+}
--- a/agent/core/src/test/java/com/redhat/thermostat/utils/management/internal/AgentProxyClientTest.java	Fri Nov 22 13:28:33 2013 -0500
+++ b/agent/core/src/test/java/com/redhat/thermostat/utils/management/internal/AgentProxyClientTest.java	Fri Nov 22 13:30:58 2013 -0500
@@ -57,6 +57,7 @@
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 
+import com.redhat.thermostat.agent.internal.RMIRegistryImpl;
 import com.redhat.thermostat.agent.proxy.common.AgentProxyControl;
 import com.redhat.thermostat.agent.proxy.common.AgentProxyListener;
 import com.redhat.thermostat.agent.proxy.common.AgentProxyLogin;
@@ -66,7 +67,7 @@
 public class AgentProxyClientTest {
     
     private AgentProxyClient client;
-    private RMIRegistry rmi;
+    private RMIRegistryImpl rmi;
     private Registry registry;
     private ProcessCreator procCreator;
     private CountDownLatch latch;
@@ -77,7 +78,7 @@
     
     @Before
     public void setup() throws Exception {
-        rmi = mock(RMIRegistry.class);
+        rmi = mock(RMIRegistryImpl.class);
         listenerStub = mock(AgentProxyListener.class);
         when(rmi.export(any(AgentProxyListener.class))).thenReturn(listenerStub);
         registry = mock(Registry.class);
--- a/agent/core/src/test/java/com/redhat/thermostat/utils/management/internal/MXBeanConnectionPoolImplTest.java	Fri Nov 22 13:28:33 2013 -0500
+++ b/agent/core/src/test/java/com/redhat/thermostat/utils/management/internal/MXBeanConnectionPoolImplTest.java	Fri Nov 22 13:30:58 2013 -0500
@@ -50,6 +50,7 @@
 
 import org.junit.Test;
 
+import com.redhat.thermostat.agent.internal.RMIRegistryImpl;
 import com.redhat.thermostat.utils.management.MXBeanConnection;
 import com.redhat.thermostat.utils.management.internal.MXBeanConnectionPoolImpl.ConnectorCreator;
 
@@ -63,10 +64,10 @@
         MXBeanConnector connector = mock(MXBeanConnector.class);
         ConnectorCreator creator = mock(ConnectorCreator.class);
 
-        when(creator.create(any(RMIRegistry.class), anyInt(), any(File.class))).thenReturn(connector);
+        when(creator.create(any(RMIRegistryImpl.class), anyInt(), any(File.class))).thenReturn(connector);
         when(connector.connect()).thenReturn(toReturn);
 
-        RMIRegistry registry = mock(RMIRegistry.class);
+        RMIRegistryImpl registry = mock(RMIRegistryImpl.class);
         MXBeanConnectionPoolImpl pool = new MXBeanConnectionPoolImpl(creator, registry, binDir);
 
         MXBeanConnection connection = pool.acquire(0);
@@ -85,10 +86,10 @@
         MXBeanConnector connector = mock(MXBeanConnector.class);
         ConnectorCreator creator = mock(ConnectorCreator.class);
 
-        when(creator.create(any(RMIRegistry.class), anyInt(), any(File.class))).thenReturn(connector);
+        when(creator.create(any(RMIRegistryImpl.class), anyInt(), any(File.class))).thenReturn(connector);
         when(connector.connect()).thenReturn(toReturn);
 
-        RMIRegistry registry = mock(RMIRegistry.class);
+        RMIRegistryImpl registry = mock(RMIRegistryImpl.class);
         MXBeanConnectionPoolImpl pool = new MXBeanConnectionPoolImpl(creator, registry, binDir);
 
         MXBeanConnection connection1 = pool.acquire(0);
@@ -111,10 +112,10 @@
         MXBeanConnector connector = mock(MXBeanConnector.class);
         ConnectorCreator creator = mock(ConnectorCreator.class);
 
-        when(creator.create(any(RMIRegistry.class), anyInt(), any(File.class))).thenReturn(connector);
+        when(creator.create(any(RMIRegistryImpl.class), anyInt(), any(File.class))).thenReturn(connector);
         when(connector.connect()).thenReturn(actualConnection);
 
-        RMIRegistry registry = mock(RMIRegistry.class);
+        RMIRegistryImpl registry = mock(RMIRegistryImpl.class);
         MXBeanConnectionPoolImpl pool = new MXBeanConnectionPoolImpl(creator, registry, binDir);
 
         MXBeanConnection connection = pool.acquire(0);
@@ -132,10 +133,10 @@
         MXBeanConnector connector = mock(MXBeanConnector.class);
         ConnectorCreator creator = mock(ConnectorCreator.class);
 
-        when(creator.create(any(RMIRegistry.class), anyInt(), any(File.class))).thenReturn(connector);
+        when(creator.create(any(RMIRegistryImpl.class), anyInt(), any(File.class))).thenReturn(connector);
         when(connector.connect()).thenReturn(actualConnection);
 
-        RMIRegistry registry = mock(RMIRegistry.class);
+        RMIRegistryImpl registry = mock(RMIRegistryImpl.class);
         MXBeanConnectionPoolImpl pool = new MXBeanConnectionPoolImpl(creator, registry, binDir);
 
         // connection1 == connection1 == actualConnection
@@ -154,7 +155,7 @@
     
     @Test
     public void testShutdown() throws Exception {
-        RMIRegistry registry = mock(RMIRegistry.class);
+        RMIRegistryImpl registry = mock(RMIRegistryImpl.class);
         ConnectorCreator creator = mock(ConnectorCreator.class);
         MXBeanConnectionPoolImpl pool = new MXBeanConnectionPoolImpl(creator, registry, binDir);
         verify(registry).start();
--- a/agent/core/src/test/java/com/redhat/thermostat/utils/management/internal/RMIRegistryTest.java	Fri Nov 22 13:28:33 2013 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-package com.redhat.thermostat.utils.management.internal;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.rmi.registry.Registry;
-import java.rmi.server.RMIClientSocketFactory;
-import java.rmi.server.RMIServerSocketFactory;
-import java.rmi.server.RMISocketFactory;
-
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-import com.redhat.thermostat.utils.management.internal.RMIRegistry.RegistryCreator;
-import com.redhat.thermostat.utils.management.internal.RMIRegistry.ServerSocketCreator;
-
-public class RMIRegistryTest {
-    
-    @Test
-    public void testRegistryStart() throws IOException {
-        RegistryCreator creator = mock(RegistryCreator.class);
-        Registry reg = mock(Registry.class);
-        when(creator.createRegistry(anyInt(), any(RMIClientSocketFactory.class), 
-                any(RMIServerSocketFactory.class))).thenReturn(reg);
-        ServerSocketCreator sockCreator = mock(ServerSocketCreator.class);
-        
-        RMIRegistry registry = new RMIRegistry(creator, sockCreator);
-        registry.start();
-        
-        ArgumentCaptor<Integer> portCaptor = ArgumentCaptor.forClass(Integer.class);
-        ArgumentCaptor<RMIClientSocketFactory> csfCaptor = ArgumentCaptor.forClass(RMIClientSocketFactory.class);
-        ArgumentCaptor<RMIServerSocketFactory> ssfCaptor = ArgumentCaptor.forClass(RMIServerSocketFactory.class);
-        verify(creator).createRegistry(portCaptor.capture(), csfCaptor.capture(), ssfCaptor.capture());
-        
-        // Ensure defaults used for port and client socket factory
-        int port = portCaptor.getValue();
-        assertEquals(Registry.REGISTRY_PORT, port);
-        
-        RMIClientSocketFactory csf = csfCaptor.getValue();
-        assertEquals(RMISocketFactory.getDefaultSocketFactory(), csf);
-        
-        // Ensure bound to loopback address
-        RMIServerSocketFactory ssf = ssfCaptor.getValue();
-        ssf.createServerSocket(port);
-        verify(sockCreator).createSocket(port, 0, InetAddress.getLoopbackAddress());
-    }
-    
-    @Test
-    public void testRegistryStop() throws IOException {
-        RegistryCreator creator = mock(RegistryCreator.class);
-        Registry reg = mock(Registry.class);
-        when(creator.createRegistry(anyInt(), any(RMIClientSocketFactory.class), 
-                any(RMIServerSocketFactory.class))).thenReturn(reg);
-        ServerSocketCreator sockCreator = mock(ServerSocketCreator.class);
-        
-        RMIRegistry registry = new RMIRegistry(creator, sockCreator);
-        registry.start();
-        
-        registry.stop();
-        
-        verify(creator).destroyRegistry(reg);
-        assertNull(registry.getRegistryImpl());
-    }
-    
-    @Test
-    public void testRegistryStopNotStarted() throws IOException {
-        RegistryCreator creator = mock(RegistryCreator.class);
-        Registry reg = mock(Registry.class);
-        when(creator.createRegistry(anyInt(), any(RMIClientSocketFactory.class), 
-                any(RMIServerSocketFactory.class))).thenReturn(reg);
-        ServerSocketCreator sockCreator = mock(ServerSocketCreator.class);
-        
-        RMIRegistry registry = new RMIRegistry(creator, sockCreator);
-        
-        registry.stop();
-        
-        verify(creator, never()).destroyRegistry(reg);
-    }
-    
-}