diff --git a/SOURCES/agent_remove_rmi.patch b/SOURCES/agent_remove_rmi.patch new file mode 100644 index 0000000..2b0595a --- /dev/null +++ b/SOURCES/agent_remove_rmi.patch @@ -0,0 +1,4169 @@ +diff -urN thermostat-1.0.4.old/agent/core/pom.xml thermostat-1.0.4/agent/core/pom.xml +--- thermostat-1.0.4.old/agent/core/pom.xml 2014-12-05 14:25:31.346043250 -0500 ++++ thermostat-1.0.4/agent/core/pom.xml 2014-12-05 14:26:44.814483946 -0500 +@@ -75,11 +75,6 @@ + + + com.redhat.thermostat +- thermostat-agent-proxy-common +- ${project.version} +- +- +- com.redhat.thermostat + thermostat-launcher + ${project.version} + +diff -urN thermostat-1.0.4.old/agent/core/src/main/java/com/redhat/thermostat/agent/internal/Activator.java thermostat-1.0.4/agent/core/src/main/java/com/redhat/thermostat/agent/internal/Activator.java +--- thermostat-1.0.4.old/agent/core/src/main/java/com/redhat/thermostat/agent/internal/Activator.java 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/core/src/main/java/com/redhat/thermostat/agent/internal/Activator.java 2014-12-05 14:26:44.814483946 -0500 +@@ -62,14 +62,15 @@ + context.registerService(RMIRegistry.class, registry, null); + ServiceReference pathsRef = context.getServiceReference(CommonPaths.class); + CommonPaths paths = context.getService(pathsRef); +- pool = new MXBeanConnectionPoolImpl(registry, paths.getSystemBinRoot()); ++ UserNameUtilImpl usernameUtil = new UserNameUtilImpl(); ++ context.registerService(UserNameUtil.class, usernameUtil, null); ++ pool = new MXBeanConnectionPoolImpl(paths.getSystemBinRoot(), usernameUtil); + context.registerService(MXBeanConnectionPool.class, pool, null); + StorageCredentials creds = new AgentStorageCredentials(paths.getUserAgentAuthConfigFile()); + context.registerService(StorageCredentials.class, creds, null); + AgentConfigsUtils.setConfigFiles(paths.getSystemAgentConfigurationFile(), paths.getUserAgentConfigurationFile()); + paths = null; + context.ungetService(pathsRef); +- context.registerService(UserNameUtil.class, new UserNameUtilImpl(), null); + VmBlacklistImpl blacklist = new VmBlacklistImpl(); + blacklist.addVmFilter(new AgentProxyFilter()); + context.registerService(VmBlacklist.class, blacklist, null); +@@ -78,10 +79,7 @@ + @Override + public void stop(BundleContext context) throws Exception { + // Services automatically unregistered by framework +- if (pool != null) { +- pool.shutdown(); +- pool = null; +- } ++ pool = null; + } + + // Testing hook. +diff -urN thermostat-1.0.4.old/agent/core/src/main/java/com/redhat/thermostat/agent/internal/RMIRegistryImpl.java thermostat-1.0.4/agent/core/src/main/java/com/redhat/thermostat/agent/internal/RMIRegistryImpl.java +--- thermostat-1.0.4.old/agent/core/src/main/java/com/redhat/thermostat/agent/internal/RMIRegistryImpl.java 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/core/src/main/java/com/redhat/thermostat/agent/internal/RMIRegistryImpl.java 2014-12-05 14:26:44.815483952 -0500 +@@ -36,120 +36,31 @@ + + 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; + ++@Deprecated + 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"); ++ RMIRegistryImpl() { + } + + @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"); +- } ++ throw new RemoteException("RMI is no longer used"); + } + + @Override + public Remote export(Remote obj) throws RemoteException { +- if (registry == null) { +- throw new RemoteException("RMI registry is not running"); +- } +- return registryWrapper.export(obj, 0); ++ throw new RemoteException("RMI is no longer used"); + } + + @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; ++ throw new RemoteException("RMI is no longer used"); + } + +- 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); +- } +- } +- + } +diff -urN thermostat-1.0.4.old/agent/core/src/main/java/com/redhat/thermostat/agent/RMIRegistry.java thermostat-1.0.4/agent/core/src/main/java/com/redhat/thermostat/agent/RMIRegistry.java +--- thermostat-1.0.4.old/agent/core/src/main/java/com/redhat/thermostat/agent/RMIRegistry.java 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/core/src/main/java/com/redhat/thermostat/agent/RMIRegistry.java 2014-12-05 14:26:44.816483958 -0500 +@@ -45,8 +45,13 @@ + /** + * Maintains an RMI registry used for inter-process communication between + * the Thermostat agent and other helper processes on the same host. ++ * ++ *

++ * RMI is no longer used by the Thermostat agent. Invoking any of this ++ * service's methods will result in a {@link RemoteException}. + */ + @Service ++@Deprecated + public interface RMIRegistry { + + /** +diff -urN thermostat-1.0.4.old/agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/AgentProxyClient.java thermostat-1.0.4/agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/AgentProxyClient.java +--- thermostat-1.0.4.old/agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/AgentProxyClient.java 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/AgentProxyClient.java 2014-12-05 14:26:44.816483958 -0500 +@@ -36,141 +36,107 @@ + + package com.redhat.thermostat.utils.management.internal; + ++import java.io.BufferedReader; + import java.io.File; + import java.io.IOException; +-import java.rmi.NotBoundException; +-import java.rmi.RemoteException; +-import java.rmi.registry.Registry; +-import java.util.concurrent.CountDownLatch; +-import java.util.concurrent.TimeUnit; ++import java.io.InputStream; ++import java.io.InputStreamReader; ++import java.util.logging.Level; + 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; + import com.redhat.thermostat.common.tools.ApplicationException; +-import com.redhat.thermostat.common.utils.LoggedExternalProcess; + import com.redhat.thermostat.common.utils.LoggingUtils; + +-class AgentProxyClient implements AgentProxyListener { ++class AgentProxyClient { + +- private static final long SERVER_TIMEOUT_MS = 5000L; + private static final String SERVER_NAME = "thermostat-agent-proxy"; + private static final Logger logger = LoggingUtils.getLogger(AgentProxyClient.class); + +- private final RMIRegistry registry; + private final int pid; + private final ProcessCreator procCreator; + private final File binPath; +- private final CountDownLatch started; ++ private final String username; + +- private AgentProxyControl proxy; +- private Exception serverError; +- +- AgentProxyClient(RMIRegistry registry, int pid, File binPath) { +- this(registry, pid, binPath, new CountDownLatch(1), +- new ProcessCreator()); ++ AgentProxyClient(int pid, String user, File binPath) { ++ this(pid, user, binPath, new ProcessCreator()); + } + +- AgentProxyClient(RMIRegistry registry, int pid, File binPath, +- CountDownLatch started, ProcessCreator procCreator) { +- this.registry = registry; ++ AgentProxyClient(int pid, String user, File binPath, ProcessCreator procCreator) { + this.pid = pid; + this.binPath = binPath; +- this.started = started; + this.procCreator = procCreator; ++ this.username = user; + } + +- void createProxy() throws IOException, ApplicationException { +- // Export our listener +- AgentProxyListener stub = (AgentProxyListener) registry.export(this); +- String listenerName = REMOTE_PREFIX + String.valueOf(pid); +- Registry reg = registry.getRegistry(); +- reg.rebind(listenerName, stub); +- logger.fine("Registered proxy listener for " + pid); +- +- // Start the agent proxy, and wait until it exports itself ++ String getJMXServiceURL() throws IOException, ApplicationException { ++ // Start the agent proxy ++ Process proxy = null; ++ Thread errReaderThread = null; + try { +- startProcess(); +- } finally { +- // Got started event or timed out, unregister our listener +- try { +- reg.unbind(listenerName); +- registry.unexport(this); +- } catch (NotBoundException e) { +- throw new RemoteException("Error unregistering listener", e); +- } +- } ++ proxy = startProcess(); + +- // Check if server started successfully +- if (serverError != null) { +- throw new RemoteException("Server failed to start", serverError); +- } ++ final InputStream errStream = proxy.getErrorStream(); + +- // Lookup server +- String serverName = AgentProxyLogin.REMOTE_PREFIX + String.valueOf(pid); +- try { +- // Need to authenticate in order to obtain proxy object +- AgentProxyLogin proxyLogin = (AgentProxyLogin) reg.lookup(serverName); +- proxy = proxyLogin.login(); +- } catch (NotBoundException e) { +- throw new RemoteException("Unable to find remote interface", e); +- } +- } ++ // Log stderr in a separate thread ++ errReaderThread = new Thread(new Runnable() { ++ @Override ++ public void run() { ++ BufferedReader errReader = new BufferedReader(new InputStreamReader(errStream)); ++ String line; ++ try { ++ while ((line = errReader.readLine()) != null ++ && !Thread.currentThread().isInterrupted()) { ++ logger.info(line); ++ } ++ errReader.close(); ++ } catch (IOException e) { ++ logger.log(Level.WARNING, "Failed to read error stream", e); ++ } ++ } ++ }); ++ errReaderThread.start(); ++ ++ // Get JMX service URL from stdout ++ BufferedReader outReader = new BufferedReader(new InputStreamReader(proxy.getInputStream())); ++ String url = outReader.readLine(); + +- private void startProcess() throws IOException, ApplicationException { +- String serverPath = binPath + File.separator + SERVER_NAME; +- procCreator.createAndRunProcess(new String[] { serverPath, String.valueOf(pid) }); +- try { +- boolean result = started.await(SERVER_TIMEOUT_MS, TimeUnit.MILLISECONDS); +- if (!result) { +- throw new RemoteException("Timeout while waiting for server"); ++ // Wait for process to terminate ++ try { ++ proxy.waitFor(); ++ } catch (InterruptedException e) { ++ errReaderThread.interrupt(); ++ Thread.currentThread().interrupt(); ++ } ++ outReader.close(); ++ if (url == null) { ++ throw new IOException("Failed to determine JMX service URL from proxy process"); ++ } ++ ++ return url; ++ } finally { ++ if (proxy != null) { ++ proxy.destroy(); ++ } ++ if (errReaderThread != null) { ++ try { ++ errReaderThread.join(); ++ } catch (InterruptedException e) { ++ errReaderThread.interrupt(); ++ Thread.currentThread().interrupt(); ++ } + } +- } catch (InterruptedException e) { +- // Restore interrupted status +- Thread.currentThread().interrupt(); + } + } +- +- void attach() throws RemoteException { +- proxy.attach(); +- } +- +- boolean isAttached() throws RemoteException { +- return proxy.isAttached(); +- } +- +- String getConnectorAddress() throws RemoteException { +- return proxy.getConnectorAddress(); +- } +- +- void detach() throws RemoteException { +- proxy.detach(); +- } +- +- @Override +- public void serverStarted() throws RemoteException { +- started.countDown(); +- } + +- @Override +- public void serverFailedToStart(Exception error) throws RemoteException { +- serverError = error; +- started.countDown(); +- } +- +- /* +- * For testing purposes only. +- */ +- AgentProxyControl getProxy() { +- return proxy; ++ private Process startProcess() throws IOException, ApplicationException { ++ String serverPath = binPath + File.separator + SERVER_NAME; ++ return procCreator.createAndRunProcess(new String[] { serverPath, String.valueOf(pid), username }); + } + + static class ProcessCreator { + Process createAndRunProcess(String[] args) throws IOException, ApplicationException { +- LoggedExternalProcess process = new LoggedExternalProcess(args); +- return process.runAndReturnProcess(); ++ ProcessBuilder process = new ProcessBuilder(args); ++ return process.start(); + } + } + +diff -urN thermostat-1.0.4.old/agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/MXBeanConnectionPoolImpl.java thermostat-1.0.4/agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/MXBeanConnectionPoolImpl.java +--- thermostat-1.0.4.old/agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/MXBeanConnectionPoolImpl.java 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/MXBeanConnectionPoolImpl.java 2014-12-05 14:26:44.817483964 -0500 +@@ -38,46 +38,34 @@ + + import java.io.File; + import java.io.IOException; +-import java.rmi.RemoteException; + import java.util.HashMap; + import java.util.Map; +-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.agent.utils.ProcDataSource; + import com.redhat.thermostat.agent.utils.management.MXBeanConnection; + import com.redhat.thermostat.agent.utils.management.MXBeanConnectionPool; ++import com.redhat.thermostat.agent.utils.username.UserNameUtil; + import com.redhat.thermostat.common.Pair; + import com.redhat.thermostat.common.tools.ApplicationException; +-import com.redhat.thermostat.common.utils.LoggingUtils; ++import com.redhat.thermostat.utils.management.internal.ProcessUserInfoBuilder.ProcessUserInfo; + + public class MXBeanConnectionPoolImpl implements MXBeanConnectionPool { + +- private static final Logger logger = LoggingUtils.getLogger(MXBeanConnectionPoolImpl.class); +- + // pid -> (usageCount, actualObject) + private Map> pool = new HashMap<>(); + + private final ConnectorCreator creator; +- private final RMIRegistryImpl registry; + private final File binPath; ++ private final ProcessUserInfoBuilder userInfoBuilder; + +- public MXBeanConnectionPoolImpl(RMIRegistryImpl registry, File binPath) { +- this(new ConnectorCreator(), registry, binPath); ++ public MXBeanConnectionPoolImpl(File binPath, UserNameUtil userNameUtil) { ++ this(new ConnectorCreator(), binPath, new ProcessUserInfoBuilder(new ProcDataSource(), userNameUtil)); + } + +- MXBeanConnectionPoolImpl(ConnectorCreator connectorCreator, RMIRegistryImpl registry, File binPath) { ++ MXBeanConnectionPoolImpl(ConnectorCreator connectorCreator, File binPath, ProcessUserInfoBuilder userInfoBuilder) { + this.creator = connectorCreator; +- this.registry = registry; + this.binPath = binPath; +- +- // Start RMI registry +- try { +- registry.start(); +- } catch (RemoteException e) { +- logger.log(Level.SEVERE, "Unable to start RMI registry", e); +- } ++ this.userInfoBuilder = userInfoBuilder; + } + + @Override +@@ -85,16 +73,14 @@ + Pair data = pool.get(pid); + if (data == null) { + MXBeanConnector connector = null; +- try { +- connector = creator.create(registry, pid, binPath); +- connector.attach(); +- MXBeanConnectionImpl connection = connector.connect(); +- data = new Pair(1, connection); +- } finally { +- if (connector != null) { +- connector.close(); +- } ++ ProcessUserInfo info = userInfoBuilder.build(pid); ++ String username = info.getUsername(); ++ if (username == null) { ++ throw new IOException("Unable to determine owner of " + pid); + } ++ connector = creator.create(pid, username, binPath); ++ MXBeanConnectionImpl connection = connector.connect(); ++ data = new Pair(1, connection); + } else { + data = new Pair<>(data.getFirst() + 1, data.getSecond()); + } +@@ -117,17 +103,9 @@ + } + } + +- public void shutdown() { +- try { +- registry.stop(); +- } catch (RemoteException e) { +- logger.log(Level.SEVERE, "Unable to stop RMI registry", e); +- } +- } +- + static class ConnectorCreator { +- public MXBeanConnector create(RMIRegistry registry, int pid, File binPath) throws IOException, ApplicationException { +- MXBeanConnector connector = new MXBeanConnector(registry, pid, binPath); ++ public MXBeanConnector create(int pid, String user, File binPath) throws IOException, ApplicationException { ++ MXBeanConnector connector = new MXBeanConnector(pid, user, binPath); + return connector; + } + } +diff -urN thermostat-1.0.4.old/agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/MXBeanConnector.java thermostat-1.0.4/agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/MXBeanConnector.java +--- thermostat-1.0.4.old/agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/MXBeanConnector.java 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/MXBeanConnector.java 2014-12-05 14:26:44.817483964 -0500 +@@ -36,40 +36,32 @@ + + package com.redhat.thermostat.utils.management.internal; + +-import java.io.Closeable; + import java.io.File; + import java.io.IOException; +-import java.rmi.RemoteException; + + import javax.management.MBeanServerConnection; + import javax.management.remote.JMXConnector; + 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 { ++class MXBeanConnector { + +- private final AgentProxyClient client; + private final JMXConnectionCreator jmxCreator; ++ private final String serviceURL; + +- public MXBeanConnector(RMIRegistry registry, int pid, File binPath) throws IOException, ApplicationException { +- this(new AgentProxyClient(registry, pid, binPath), new JMXConnectionCreator()); ++ public MXBeanConnector(int pid, String user, File binPath) throws IOException, ApplicationException { ++ this(new AgentProxyClient(pid, user, binPath), new JMXConnectionCreator()); + } + + MXBeanConnector(AgentProxyClient client, JMXConnectionCreator jmxCreator) throws IOException, ApplicationException { +- this.client = client; + this.jmxCreator = jmxCreator; +- client.createProxy(); +- } +- +- public synchronized void attach() throws Exception { +- client.attach(); ++ this.serviceURL = client.getJMXServiceURL(); + } + + public synchronized MXBeanConnectionImpl connect() throws IOException { +- JMXServiceURL url = new JMXServiceURL(client.getConnectorAddress()); ++ JMXServiceURL url = new JMXServiceURL(serviceURL); + JMXConnector connection = jmxCreator.create(url); + MBeanServerConnection mbsc = null; + try { +@@ -83,15 +75,6 @@ + return new MXBeanConnectionImpl(connection, mbsc); + } + +- public boolean isAttached() throws RemoteException { +- return client.isAttached(); +- } +- +- @Override +- public synchronized void close() throws IOException { +- client.detach(); +- } +- + static class JMXConnectionCreator { + JMXConnector create(JMXServiceURL url) throws IOException { + return JMXConnectorFactory.connect(url); +diff -urN thermostat-1.0.4.old/agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/ProcessUserInfoBuilder.java thermostat-1.0.4/agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/ProcessUserInfoBuilder.java +--- thermostat-1.0.4.old/agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/ProcessUserInfoBuilder.java 1969-12-31 19:00:00.000000000 -0500 ++++ thermostat-1.0.4/agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/ProcessUserInfoBuilder.java 2014-12-05 14:26:44.818483970 -0500 +@@ -0,0 +1,140 @@ ++/* ++ * 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 ++ * . ++ * ++ * 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.BufferedReader; ++import java.io.IOException; ++import java.io.Reader; ++import java.util.logging.Level; ++import java.util.logging.Logger; ++ ++import com.redhat.thermostat.agent.utils.ProcDataSource; ++import com.redhat.thermostat.agent.utils.username.UserNameLookupException; ++import com.redhat.thermostat.agent.utils.username.UserNameUtil; ++import com.redhat.thermostat.common.utils.LoggingUtils; ++ ++/* ++ * FIXME: This class was copied from system-backend to avoid adding new API. ++ */ ++class ProcessUserInfoBuilder { ++ ++ private static final ProcessUserInfo NON_EXISTENT_USER = new ProcessUserInfo(); ++ private static final String PROC_STATUS_UID = "Uid:"; ++ private static final Logger logger = LoggingUtils.getLogger(ProcessUserInfoBuilder.class); ++ private ProcDataSource source; ++ private UserNameUtil userNameUtil; ++ ++ ProcessUserInfoBuilder(ProcDataSource source, UserNameUtil userNameUtil) { ++ this.source = source; ++ this.userNameUtil = userNameUtil; ++ } ++ ++ static class ProcessUserInfo { ++ ++ private long uid; ++ private String username; ++ ++ ProcessUserInfo(long uid, String username) { ++ this.uid = uid; ++ this.username = username; ++ } ++ ++ ProcessUserInfo() { ++ this.uid = -1; ++ this.username = null; ++ } ++ ++ public long getUid() { ++ return uid; ++ } ++ ++ public String getUsername() { ++ return username; ++ } ++ } ++ ++ ProcessUserInfo build(int pid) { ++ ProcessUserInfo info = NON_EXISTENT_USER; ++ try { ++ Reader reader = source.getStatusReader(pid); ++ long uid = getUidFromProcfs(new BufferedReader(reader)); ++ String name = null; ++ try { ++ name = userNameUtil.getUserName(uid); ++ } catch (UserNameLookupException e) { ++ logger.log(Level.WARNING, "Unable to retrieve username for uid: " + uid, e); ++ } ++ info = new ProcessUserInfo(uid, name); ++ } catch (IOException e) { ++ logger.log(Level.WARNING, "Unable to read user info for " + pid, e); ++ } ++ ++ return info; ++ } ++ ++ /* ++ * Look for the following line: ++ * Uid: ++ */ ++ private long getUidFromProcfs(BufferedReader br) throws IOException { ++ long uid = -1; ++ String line; ++ while ((line = br.readLine()) != null) { ++ line = line.trim(); ++ if (line.startsWith(PROC_STATUS_UID)) { ++ String[] parts = line.split("\\s+"); ++ if (parts.length == 5) { ++ try { ++ // Use Real UID ++ uid = Long.parseLong(parts[1]); ++ } catch (NumberFormatException e) { ++ throw new IOException("Unexpected output from ps command", e); ++ } ++ } ++ else { ++ throw new IOException("Expected 5 parts from split /proc/${pid}/status output, got " + parts.length); ++ } ++ } ++ } ++ if (uid < 0) { ++ throw new IOException("Unable to determine UID from /proc/${pid}/status"); ++ } ++ return uid; ++ } ++ ++ ++} +diff -urN thermostat-1.0.4.old/agent/core/src/test/java/com/redhat/thermostat/agent/internal/ActivatorTest.java thermostat-1.0.4/agent/core/src/test/java/com/redhat/thermostat/agent/internal/ActivatorTest.java +--- thermostat-1.0.4.old/agent/core/src/test/java/com/redhat/thermostat/agent/internal/ActivatorTest.java 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/core/src/test/java/com/redhat/thermostat/agent/internal/ActivatorTest.java 2014-12-05 14:26:44.818483970 -0500 +@@ -89,7 +89,5 @@ + activator.setPool(pool); + + activator.stop(context); +- +- verify(pool).shutdown(); + } + } +diff -urN thermostat-1.0.4.old/agent/core/src/test/java/com/redhat/thermostat/agent/internal/RMIRegistryImplTest.java thermostat-1.0.4/agent/core/src/test/java/com/redhat/thermostat/agent/internal/RMIRegistryImplTest.java +--- thermostat-1.0.4.old/agent/core/src/test/java/com/redhat/thermostat/agent/internal/RMIRegistryImplTest.java 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/core/src/test/java/com/redhat/thermostat/agent/internal/RMIRegistryImplTest.java 2014-12-05 14:26:44.819483976 -0500 +@@ -1,122 +1,35 @@ + 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 portCaptor = ArgumentCaptor.forClass(Integer.class); +- ArgumentCaptor csfCaptor = ArgumentCaptor.forClass(RMIClientSocketFactory.class); +- ArgumentCaptor 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()); ++ public void setup() throws Exception { ++ registry = new RMIRegistryImpl(); + } + +- @Test +- public void testRegistryStopNotStarted() throws IOException { +- registry.stop(); +- +- verify(wrapper, never()).destroyRegistry(reg); +- } +- +- @Test ++ @Test(expected=RemoteException.class) + 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)); ++ registry.getRegistry(); + } + + @Test(expected=RemoteException.class) +- public void testExportObjectNotStarted() throws Exception { ++ public void testExportObject() 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 { ++ public void testUnexportObject() throws Exception { + Remote obj = mock(Remote.class); + registry.unexport(obj); + } +diff -urN thermostat-1.0.4.old/agent/core/src/test/java/com/redhat/thermostat/utils/management/internal/AgentProxyClientTest.java thermostat-1.0.4/agent/core/src/test/java/com/redhat/thermostat/utils/management/internal/AgentProxyClientTest.java +--- thermostat-1.0.4.old/agent/core/src/test/java/com/redhat/thermostat/utils/management/internal/AgentProxyClientTest.java 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/core/src/test/java/com/redhat/thermostat/utils/management/internal/AgentProxyClientTest.java 2014-12-05 14:26:44.819483976 -0500 +@@ -37,185 +37,116 @@ + package com.redhat.thermostat.utils.management.internal; + + import static org.junit.Assert.assertEquals; +-import static org.junit.Assert.assertTrue; + import static org.junit.Assert.fail; + import static org.mockito.Matchers.any; +-import static org.mockito.Mockito.doAnswer; + import static org.mockito.Mockito.mock; + import static org.mockito.Mockito.verify; + import static org.mockito.Mockito.when; + ++import java.io.ByteArrayInputStream; + import java.io.File; + import java.io.IOException; +-import java.rmi.RemoteException; +-import java.rmi.registry.Registry; +-import java.util.concurrent.CountDownLatch; +-import java.util.concurrent.TimeUnit; ++import java.util.ArrayList; ++import java.util.List; ++import java.util.logging.Handler; ++import java.util.logging.LogRecord; + + import org.junit.Before; + import org.junit.Test; +-import org.mockito.invocation.InvocationOnMock; +-import org.mockito.stubbing.Answer; ++import org.mockito.ArgumentCaptor; + +-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; +-import com.redhat.thermostat.common.tools.ApplicationException; ++import com.redhat.thermostat.common.utils.LoggingUtils; + import com.redhat.thermostat.utils.management.internal.AgentProxyClient.ProcessCreator; + + public class AgentProxyClientTest { + + private AgentProxyClient client; +- private RMIRegistryImpl rmi; +- private Registry registry; + private ProcessCreator procCreator; +- private CountDownLatch latch; +- private AgentProxyListener listenerStub; +- private AgentProxyLogin proxyLogin; +- private AgentProxyControl proxyControl; ++ private String user; + private File binPath; + + @Before + public void setup() throws Exception { +- rmi = mock(RMIRegistryImpl.class); +- listenerStub = mock(AgentProxyListener.class); +- when(rmi.export(any(AgentProxyListener.class))).thenReturn(listenerStub); +- registry = mock(Registry.class); +- when(rmi.getRegistry()).thenReturn(registry); +- proxyLogin = mock(AgentProxyLogin.class); +- when(registry.lookup(AgentProxyLogin.REMOTE_PREFIX + "0")).thenReturn(proxyLogin); +- proxyControl = mock(AgentProxyControl.class); +- when(proxyLogin.login()).thenReturn(proxyControl); +- + procCreator = mock(ProcessCreator.class); + binPath = new File("/path/to/thermostat/bin"); +- latch = mock(CountDownLatch.class); ++ user = "Hello"; ++ client = new AgentProxyClient(9000, user, binPath, procCreator); + } + + @Test + public void testCreateProxy() throws Exception { +- createClient(); +- +- // Verify listener exported and bound +- verify(rmi).export(client); +- verify(registry).rebind(AgentProxyListener.REMOTE_PREFIX + "0", listenerStub); +- +- // Verify server created +- String progName = "/path/to/thermostat/bin" + File.separator + "thermostat-agent-proxy"; +- verify(procCreator).createAndRunProcess(new String[] { progName, "0" }); +- verify(latch).countDown(); +- +- // Verify listener removed +- verify(registry).unbind(AgentProxyListener.REMOTE_PREFIX + "0"); +- verify(rmi).unexport(client); +- +- // Verify login +- verify(registry).lookup(AgentProxyLogin.REMOTE_PREFIX + "0"); +- verify(proxyLogin).login(); +- +- // Check returned proxy control +- assertEquals(proxyControl, client.getProxy()); +- } +- +- private void createClient() throws InterruptedException, IOException, +- ApplicationException { +- client = new AgentProxyClient(rmi, 0, binPath, latch, procCreator); +- +- doAnswer(new Answer() { +- @Override +- public Boolean answer(InvocationOnMock invocation) throws Throwable { +- // Trigger server started +- client.serverStarted(); +- return true; +- } +- }).when(latch).await(any(Long.class), any(TimeUnit.class)); +- +- client.createProxy(); ++ Process proxy = mock(Process.class); ++ final String jmxUrl = "myJmxUrl"; ++ when(proxy.getInputStream()).thenReturn(new ByteArrayInputStream(jmxUrl.getBytes())); ++ when(proxy.getErrorStream()).thenReturn(new ByteArrayInputStream(new byte[0])); ++ when(procCreator.createAndRunProcess(any(String[].class))).thenReturn(proxy); ++ ++ // Check returned URL ++ String result = client.getJMXServiceURL(); ++ assertEquals(jmxUrl, result); ++ ++ // Check process arguments ++ ArgumentCaptor argsCaptor = ArgumentCaptor.forClass(String[].class); ++ verify(procCreator).createAndRunProcess(argsCaptor.capture()); ++ String[] args = argsCaptor.getValue(); ++ assertEquals(3, args.length); ++ assertEquals("/path/to/thermostat/bin/thermostat-agent-proxy", args[0]); ++ assertEquals("9000", args[1]); ++ assertEquals("Hello", args[2]); ++ ++ // Check cleanup ++ verify(proxy).waitFor(); + } + + @Test +- public void testCreateProxyFailed() throws Exception { +- client = new AgentProxyClient(rmi, 0, binPath, latch, procCreator); +- +- final Exception error = mock(Exception.class); +- doAnswer(new Answer() { +- @Override +- public Boolean answer(InvocationOnMock invocation) throws Throwable { +- // Trigger server started +- client.serverFailedToStart(error); +- return true; +- } +- }).when(latch).await(any(Long.class), any(TimeUnit.class)); ++ public void testErrorHandler() throws Exception { ++ Process proxy = mock(Process.class); ++ final String errors = "This is an error\nThis is also an error\nOh no!\n"; ++ when(proxy.getInputStream()).thenReturn(new ByteArrayInputStream(new byte[0])); ++ when(proxy.getErrorStream()).thenReturn(new ByteArrayInputStream(errors.getBytes())); ++ when(procCreator.createAndRunProcess(any(String[].class))).thenReturn(proxy); ++ ++ List logMessages = new ArrayList<>(); ++ TestLogHandler logHandler = new TestLogHandler(logMessages); ++ LoggingUtils.getLogger(AgentProxyClient.class).addHandler(logHandler); + + try { +- client.createProxy(); +- fail("Expected RemoteException"); +- } catch (RemoteException e) { +- assertEquals(error, e.getCause()); ++ try { ++ client.getJMXServiceURL(); ++ fail("Expected exception"); ++ } catch (IOException e) { ++ // Expected ++ } ++ assertEquals(3, logMessages.size()); ++ assertEquals("This is an error", logMessages.get(0).getMessage()); ++ assertEquals("This is also an error", logMessages.get(1).getMessage()); ++ assertEquals("Oh no!", logMessages.get(2).getMessage()); ++ } finally { ++ LoggingUtils.getLogger(AgentProxyClient.class).removeHandler(logHandler); + } +- +- // Verify listener exported and bound +- verify(rmi).export(client); +- verify(registry).rebind(AgentProxyListener.REMOTE_PREFIX + "0", listenerStub); +- +- // Verify server created +- String progName = "/path/to/thermostat/bin" + File.separator + "thermostat-agent-proxy"; +- verify(procCreator).createAndRunProcess(new String[] { progName, "0" }); +- verify(latch).countDown(); +- +- // Verify listener removed +- verify(registry).unbind(AgentProxyListener.REMOTE_PREFIX + "0"); +- verify(rmi).unexport(client); + } + +- @Test +- public void testCreateProxyTimeout() throws Exception { +- when(latch.await(any(Long.class), any(TimeUnit.class))).thenReturn(false); +- client = new AgentProxyClient(rmi, 0, binPath, latch, procCreator); ++ private static class TestLogHandler extends Handler { + +- try { +- client.createProxy(); +- fail("Expected RemoteException"); +- } catch (RemoteException e) { +- // Verify listener exported and bound +- verify(rmi).export(client); +- verify(registry).rebind(AgentProxyListener.REMOTE_PREFIX + "0", listenerStub); +- +- // Verify server created +- String progName = "/path/to/thermostat/bin" + File.separator + "thermostat-agent-proxy"; +- verify(procCreator).createAndRunProcess(new String[] { progName, "0" }); +- +- // Verify listener removed +- verify(registry).unbind(AgentProxyListener.REMOTE_PREFIX + "0"); +- verify(rmi).unexport(client); ++ private List logMessages; ++ public TestLogHandler(List logMessages) { ++ this.logMessages = logMessages; + } +- } +- +- @Test +- public void testAttach() throws Exception { +- createClient(); + +- client.attach(); +- verify(proxyControl).attach(); +- } +- +- @Test +- public void testIsAttached() throws Exception { +- createClient(); +- when(proxyControl.isAttached()).thenReturn(true); +- +- boolean result = client.isAttached(); +- verify(proxyControl).isAttached(); +- assertTrue(result); +- } +- +- @Test +- public void testDetach() throws Exception { +- createClient(); ++ @Override ++ public void publish(LogRecord record) { ++ logMessages.add(record); ++ } ++ ++ @Override ++ public void flush() { ++ // Do nothing ++ } + +- client.detach(); +- verify(proxyControl).detach(); ++ @Override ++ public void close() throws SecurityException { ++ // Do nothing ++ } + } +- ++ + } +diff -urN thermostat-1.0.4.old/agent/core/src/test/java/com/redhat/thermostat/utils/management/internal/MXBeanConnectionPoolImplTest.java thermostat-1.0.4/agent/core/src/test/java/com/redhat/thermostat/utils/management/internal/MXBeanConnectionPoolImplTest.java +--- thermostat-1.0.4.old/agent/core/src/test/java/com/redhat/thermostat/utils/management/internal/MXBeanConnectionPoolImplTest.java 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/core/src/test/java/com/redhat/thermostat/utils/management/internal/MXBeanConnectionPoolImplTest.java 2014-12-05 14:26:44.820483982 -0500 +@@ -50,9 +50,9 @@ + + import org.junit.Test; + +-import com.redhat.thermostat.agent.internal.RMIRegistryImpl; + import com.redhat.thermostat.agent.utils.management.MXBeanConnection; + import com.redhat.thermostat.utils.management.internal.MXBeanConnectionPoolImpl.ConnectorCreator; ++import com.redhat.thermostat.utils.management.internal.ProcessUserInfoBuilder.ProcessUserInfo; + + public class MXBeanConnectionPoolImplTest { + +@@ -64,20 +64,20 @@ + MXBeanConnector connector = mock(MXBeanConnector.class); + ConnectorCreator creator = mock(ConnectorCreator.class); + +- when(creator.create(any(RMIRegistryImpl.class), anyInt(), any(File.class))).thenReturn(connector); ++ when(creator.create(anyInt(), any(String.class), any(File.class))).thenReturn(connector); + when(connector.connect()).thenReturn(toReturn); + +- RMIRegistryImpl registry = mock(RMIRegistryImpl.class); +- MXBeanConnectionPoolImpl pool = new MXBeanConnectionPoolImpl(creator, registry, binDir); ++ ProcessUserInfoBuilder builder = mock(ProcessUserInfoBuilder.class); ++ ProcessUserInfo info = new ProcessUserInfo(0, "Test"); ++ when(builder.build(0)).thenReturn(info); ++ MXBeanConnectionPoolImpl pool = new MXBeanConnectionPoolImpl(creator, binDir, builder); + + MXBeanConnection connection = pool.acquire(0); + + assertNotNull(connection); + assertEquals(connection, toReturn); + +- verify(connector).attach(); + verify(connector).connect(); +- verify(connector).close(); + } + + @Test +@@ -86,17 +86,17 @@ + MXBeanConnector connector = mock(MXBeanConnector.class); + ConnectorCreator creator = mock(ConnectorCreator.class); + +- when(creator.create(any(RMIRegistryImpl.class), anyInt(), any(File.class))).thenReturn(connector); ++ when(creator.create(anyInt(), any(String.class), any(File.class))).thenReturn(connector); + when(connector.connect()).thenReturn(toReturn); + +- RMIRegistryImpl registry = mock(RMIRegistryImpl.class); +- MXBeanConnectionPoolImpl pool = new MXBeanConnectionPoolImpl(creator, registry, binDir); ++ ProcessUserInfoBuilder builder = mock(ProcessUserInfoBuilder.class); ++ ProcessUserInfo info = new ProcessUserInfo(0, "Test"); ++ when(builder.build(0)).thenReturn(info); ++ MXBeanConnectionPoolImpl pool = new MXBeanConnectionPoolImpl(creator, binDir, builder); + + MXBeanConnection connection1 = pool.acquire(0); + +- verify(connector).attach(); + verify(connector).connect(); +- verify(connector).close(); + + MXBeanConnection connection2 = pool.acquire(0); + +@@ -112,11 +112,13 @@ + MXBeanConnector connector = mock(MXBeanConnector.class); + ConnectorCreator creator = mock(ConnectorCreator.class); + +- when(creator.create(any(RMIRegistryImpl.class), anyInt(), any(File.class))).thenReturn(connector); ++ when(creator.create(anyInt(), any(String.class), any(File.class))).thenReturn(connector); + when(connector.connect()).thenReturn(actualConnection); + +- RMIRegistryImpl registry = mock(RMIRegistryImpl.class); +- MXBeanConnectionPoolImpl pool = new MXBeanConnectionPoolImpl(creator, registry, binDir); ++ ProcessUserInfoBuilder builder = mock(ProcessUserInfoBuilder.class); ++ ProcessUserInfo info = new ProcessUserInfo(0, "Test"); ++ when(builder.build(0)).thenReturn(info); ++ MXBeanConnectionPoolImpl pool = new MXBeanConnectionPoolImpl(creator, binDir, builder); + + MXBeanConnection connection = pool.acquire(0); + +@@ -133,11 +135,13 @@ + MXBeanConnector connector = mock(MXBeanConnector.class); + ConnectorCreator creator = mock(ConnectorCreator.class); + +- when(creator.create(any(RMIRegistryImpl.class), anyInt(), any(File.class))).thenReturn(connector); ++ when(creator.create(anyInt(), any(String.class), any(File.class))).thenReturn(connector); + when(connector.connect()).thenReturn(actualConnection); + +- RMIRegistryImpl registry = mock(RMIRegistryImpl.class); +- MXBeanConnectionPoolImpl pool = new MXBeanConnectionPoolImpl(creator, registry, binDir); ++ ProcessUserInfoBuilder builder = mock(ProcessUserInfoBuilder.class); ++ ProcessUserInfo info = new ProcessUserInfo(0, "Test"); ++ when(builder.build(0)).thenReturn(info); ++ MXBeanConnectionPoolImpl pool = new MXBeanConnectionPoolImpl(creator, binDir, builder); + + // connection1 == connection1 == actualConnection + MXBeanConnection connection1 = pool.acquire(0); +@@ -153,14 +157,4 @@ + + } + +- @Test +- public void testShutdown() throws Exception { +- RMIRegistryImpl registry = mock(RMIRegistryImpl.class); +- ConnectorCreator creator = mock(ConnectorCreator.class); +- MXBeanConnectionPoolImpl pool = new MXBeanConnectionPoolImpl(creator, registry, binDir); +- verify(registry).start(); +- +- pool.shutdown(); +- verify(registry).stop(); +- } + } +diff -urN thermostat-1.0.4.old/agent/core/src/test/java/com/redhat/thermostat/utils/management/internal/MXBeanConnectorTest.java thermostat-1.0.4/agent/core/src/test/java/com/redhat/thermostat/utils/management/internal/MXBeanConnectorTest.java +--- thermostat-1.0.4.old/agent/core/src/test/java/com/redhat/thermostat/utils/management/internal/MXBeanConnectorTest.java 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/core/src/test/java/com/redhat/thermostat/utils/management/internal/MXBeanConnectorTest.java 2014-12-05 14:26:44.821483988 -0500 +@@ -37,7 +37,6 @@ + package com.redhat.thermostat.utils.management.internal; + + import static org.junit.Assert.assertEquals; +-import static org.junit.Assert.assertTrue; + import static org.mockito.Mockito.mock; + import static org.mockito.Mockito.verify; + import static org.mockito.Mockito.when; +@@ -53,6 +52,8 @@ + + public class MXBeanConnectorTest { + ++ private static final String JMX_URL = "service:jmx:rmi://myHost:1099/blah"; ++ + private MXBeanConnector connector; + private JMXConnectionCreator jmxCreator; + private AgentProxyClient client; +@@ -61,47 +62,24 @@ + public void setup() throws Exception { + jmxCreator = mock(JMXConnectionCreator.class); + client = mock(AgentProxyClient.class); ++ when(client.getJMXServiceURL()).thenReturn(JMX_URL); + connector = new MXBeanConnector(client, jmxCreator); + } + + @Test + public void testInit() throws Exception { +- // MXBeanConnector constructor calls createProxy +- verify(client).createProxy(); +- } +- +- @Test +- public void testAttach() throws Exception { +- connector.attach(); +- verify(client).attach(); +- } +- +- @Test +- public void testIsAttached() throws Exception { +- when(client.isAttached()).thenReturn(true); +- boolean result = connector.isAttached(); +- verify(client).isAttached(); +- assertTrue(result); +- } +- +- @Test +- public void testClose() throws Exception { +- connector.close(); +- verify(client).detach(); ++ // MXBeanConnector constructor calls getJMXServiceURL ++ verify(client).getJMXServiceURL(); + } + + @Test + public void testConnect() throws Exception { +- String jmxUrl = "service:jmx:rmi://myHost:1099/blah"; +- when(client.getConnectorAddress()).thenReturn(jmxUrl); +- + JMXConnector jmxConnector = mock(JMXConnector.class); +- when(jmxCreator.create(new JMXServiceURL(jmxUrl))).thenReturn(jmxConnector); ++ when(jmxCreator.create(new JMXServiceURL(JMX_URL))).thenReturn(jmxConnector); + MBeanServerConnection connection = mock(MBeanServerConnection.class); + when(jmxConnector.getMBeanServerConnection()).thenReturn(connection); + + MXBeanConnectionImpl result = connector.connect(); +- verify(client).getConnectorAddress(); + assertEquals(connection, result.get()); + } + +diff -urN thermostat-1.0.4.old/agent/proxy/common/pom.xml thermostat-1.0.4/agent/proxy/common/pom.xml +--- thermostat-1.0.4.old/agent/proxy/common/pom.xml 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/proxy/common/pom.xml 1969-12-31 19:00:00.000000000 -0500 +@@ -1,82 +0,0 @@ +- +- +- +- 4.0.0 +- +- +- com.redhat.thermostat +- thermostat-agent-proxy +- 1.0.4 +- +- +- thermostat-agent-proxy-common +- Thermostat Agent Proxy Common +- bundle +- +- +- +- +- org.apache.felix +- maven-bundle-plugin +- true +- +- +- Red Hat, Inc. +- com.redhat.thermostat.agent.proxy.common +- +- com.redhat.thermostat.agent.proxy.common, +- +- +- <_nouses>true +- +- +- +- +- +- +- +- +- com.sun +- tools +- system +- ${java.home}/../lib/tools.jar +- +- +- +- +diff -urN thermostat-1.0.4.old/agent/proxy/common/src/main/java/com/redhat/thermostat/agent/proxy/common/AgentProxyControl.java thermostat-1.0.4/agent/proxy/common/src/main/java/com/redhat/thermostat/agent/proxy/common/AgentProxyControl.java +--- thermostat-1.0.4.old/agent/proxy/common/src/main/java/com/redhat/thermostat/agent/proxy/common/AgentProxyControl.java 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/proxy/common/src/main/java/com/redhat/thermostat/agent/proxy/common/AgentProxyControl.java 1969-12-31 19:00:00.000000000 -0500 +@@ -1,85 +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 +- * . +- * +- * 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.proxy.common; +- +-import java.rmi.Remote; +-import java.rmi.RemoteException; +- +-import com.sun.tools.attach.VirtualMachine; +- +-/** +- * Remote interface to allow control of a JVM using the Hotspot attach +- * mechanism. +- * +- * This interface invokes remote methods of a delegate Java process +- * which acts as a proxy between Thermostat and the target JVM. This +- * delegate is necessary in order to assume the same user and group IDs +- * as the target JVM. +- */ +-public interface AgentProxyControl extends Remote { +- +- /** +- * Attach to the target JVM using {@link VirtualMachine#attach}. +- * @throws RemoteException if the attach fails +- */ +- void attach() throws RemoteException; +- +- /** +- * @return whether the delegate is currently attached to the target +- * JVM. +- * @throws RemoteException if this method fails for any reason +- */ +- boolean isAttached() throws RemoteException; +- +- /** +- * @return an address that can be used to establish a JMX connection +- * to the target JVM. +- * @throws RemoteException if the delegate is not attached to the target +- * VM +- */ +- String getConnectorAddress() throws RemoteException; +- +- /** +- * Detaches from the target JVM that was attached previously using +- * {@link #attach()}, and terminates the remote connection to the +- * delegate Java process. +- * @throws RemoteException if the delegate failed to detach from the VM, +- * or failed to terminate the remote connection +- */ +- void detach() throws RemoteException; +- +-} +diff -urN thermostat-1.0.4.old/agent/proxy/common/src/main/java/com/redhat/thermostat/agent/proxy/common/AgentProxyListener.java thermostat-1.0.4/agent/proxy/common/src/main/java/com/redhat/thermostat/agent/proxy/common/AgentProxyListener.java +--- thermostat-1.0.4.old/agent/proxy/common/src/main/java/com/redhat/thermostat/agent/proxy/common/AgentProxyListener.java 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/proxy/common/src/main/java/com/redhat/thermostat/agent/proxy/common/AgentProxyListener.java 1969-12-31 19:00:00.000000000 -0500 +@@ -1,70 +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 +- * . +- * +- * 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.proxy.common; +- +-import java.rmi.Remote; +-import java.rmi.RemoteException; +- +-/** +- * Remote interface to allow an implementer of {@link AgentProxyControl} +- * to notify clients when it is available. +- */ +-public interface AgentProxyListener extends Remote { +- +- /** +- * By appending the PID of the target JVM, forms the name of +- * the exported remote object implementing this interface for +- * that JVM. +- */ +- public static final String REMOTE_PREFIX = "AgentProxyListener"; +- +- /** +- * To be called when an implementer of {@link AgentProxyControl} +- * has exported itself for use by clients. +- * @throws RemoteException if this method fails for any reason +- */ +- void serverStarted() throws RemoteException; +- +- /** +- * To be called when an implementer of {@link AgentProxyControl} +- * has failed to start. +- * @param error - the cause of the failure +- * @throws RemoteException if this method fails for any reason +- */ +- void serverFailedToStart(Exception error) throws RemoteException; +- +-} +diff -urN thermostat-1.0.4.old/agent/proxy/common/src/main/java/com/redhat/thermostat/agent/proxy/common/AgentProxyLogin.java thermostat-1.0.4/agent/proxy/common/src/main/java/com/redhat/thermostat/agent/proxy/common/AgentProxyLogin.java +--- thermostat-1.0.4.old/agent/proxy/common/src/main/java/com/redhat/thermostat/agent/proxy/common/AgentProxyLogin.java 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/proxy/common/src/main/java/com/redhat/thermostat/agent/proxy/common/AgentProxyLogin.java 1969-12-31 19:00:00.000000000 -0500 +@@ -1,61 +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 +- * . +- * +- * 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.proxy.common; +- +-import java.rmi.Remote; +-import java.rmi.RemoteException; +- +-public interface AgentProxyLogin extends Remote { +- +- /** +- * By appending the PID of the target JVM, forms the name of +- * the exported remote object implementing this interface for +- * that JVM. +- */ +- public static final String REMOTE_PREFIX = "AgentProxy"; +- +- /** +- * Authenticates using the currently logged in system user, and +- * if successful, returns an object to control the agent proxy. +- * @return a control object for the agent proxy +- * @throws RemoteException if this method fails for some reason +- * @throws SecurityException if the currently logged in user +- * is not authorized to log in +- */ +- AgentProxyControl login() throws RemoteException, SecurityException; +- +-} +diff -urN thermostat-1.0.4.old/agent/proxy/pom.xml thermostat-1.0.4/agent/proxy/pom.xml +--- thermostat-1.0.4.old/agent/proxy/pom.xml 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/proxy/pom.xml 2014-12-05 14:26:44.822483994 -0500 +@@ -51,7 +51,6 @@ + Thermostat Agent Proxy + + +- common + server + + +diff -urN thermostat-1.0.4.old/agent/proxy/server/Makefile thermostat-1.0.4/agent/proxy/server/Makefile +--- thermostat-1.0.4.old/agent/proxy/server/Makefile 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/proxy/server/Makefile 1969-12-31 19:00:00.000000000 -0500 +@@ -1,41 +0,0 @@ +-CC = gcc +-JAVAH = javah +-MYCFLAGS = -c -Wall -fPIC +-MYLDFLAGS = -fPIC -shared +-COPY = cp -a +- +-CLASSPATH = target/classes +-TARGET_DIR = target +- +-INCLUDE = -I $(TARGET_DIR) -I $(JAVA_HOME)/include/ -I $(JAVA_HOME)/include/linux +-SOURCES = src/main/native/AgentProxy.c +-TARGET = $(TARGET_DIR)/AgentProxy.c +-OBJECTS = $(TARGET:.c=.o) +- +-EXECUTABLE = libAgentProxy.so +- +-.PHONY: +-JNI_LIST = com.redhat.thermostat.agent.proxy.server.AgentProxyNativeUtils +- +-$(JNI_LIST): +- $(JAVAH) -force -classpath $(CLASSPATH) -d $(TARGET_DIR) $(JNI_LIST) +- +-all: $(JNI_LIST) init $(SOURCES) $(EXECUTABLE) +- +-.PHONY: +-init: +- $(COPY) $(SOURCES) $(TARGET) +- +-$(EXECUTABLE): $(OBJECTS) +- $(CC) $(OBJECTS) -o $(TARGET_DIR)/$@ $(MYLDFLAGS) $(LDFLAGS) +- +-.c.o: +- $(CC) $(MYCFLAGS) $(CFLAGS) $(INCLUDE) $< -o $@ +- +-clean-lib: +- rm -f $(TARGET_DIR)/$(EXECUTABLE) +- +-clean-obj: +- rm -f $(OBJECTS) $(TARGET) +- +-clean: clean-obj clean-lib +diff -urN thermostat-1.0.4.old/agent/proxy/server/pom.xml thermostat-1.0.4/agent/proxy/server/pom.xml +--- thermostat-1.0.4.old/agent/proxy/server/pom.xml 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/proxy/server/pom.xml 2014-12-05 14:26:44.823484000 -0500 +@@ -49,33 +49,6 @@ + Thermostat Agent Proxy Server + + +- +- +- org.codehaus.mojo +- exec-maven-plugin +- 1.2.1 +- +- +- compile +- +- exec +- +- +- +- +- make +- +- all +- +- +- +- JAVA_HOME +- ${java.home} +- +- +- +- +- + + + +@@ -110,11 +83,6 @@ + + + com.redhat.thermostat +- thermostat-agent-proxy-common +- ${project.version} +- +- +- com.redhat.thermostat + thermostat-common-core + ${project.version} + +diff -urN thermostat-1.0.4.old/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyControlImpl.java thermostat-1.0.4/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyControlImpl.java +--- thermostat-1.0.4.old/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyControlImpl.java 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyControlImpl.java 2014-12-05 14:26:44.823484000 -0500 +@@ -40,9 +40,6 @@ + import java.io.IOException; + import java.rmi.RemoteException; + import java.util.Properties; +-import java.util.Set; +- +-import javax.security.auth.Subject; + + import com.sun.tools.attach.AgentInitializationException; + import com.sun.tools.attach.AgentLoadException; +@@ -69,58 +66,44 @@ + this.vmUtils = vmUtils; + } + +- void attach(Subject user) throws RemoteException, SecurityException { +- authCheck(user); +- try { +- vm = vmUtils.attach(String.valueOf(pid)); +- attached = true; +- +- Properties props = vm.getAgentProperties(); +- connectorAddress = props.getProperty(CONNECTOR_ADDRESS_PROPERTY); +- if (connectorAddress == null) { ++ void attach() throws AttachNotSupportedException, IOException { ++ vm = vmUtils.attach(String.valueOf(pid)); ++ attached = true; ++ ++ Properties props = vm.getAgentProperties(); ++ connectorAddress = props.getProperty(CONNECTOR_ADDRESS_PROPERTY); ++ if (connectorAddress == null) { ++ String home = null; ++ String agent = null; ++ try { + props = vm.getSystemProperties(); +- String home = props.getProperty("java.home"); +- String agent = home + File.separator + "lib" + File.separator + "management-agent.jar"; ++ home = props.getProperty("java.home"); ++ agent = home + File.separator + "lib" + File.separator + "management-agent.jar"; + vm.loadAgent(agent); +- ++ + props = vm.getAgentProperties(); + connectorAddress = props.getProperty(CONNECTOR_ADDRESS_PROPERTY); ++ } catch (IOException | AgentLoadException | AgentInitializationException e) { ++ throw new RemoteException("Failed to load agent ('" + agent + "', from home '" + home + "') into VM (pid: " + pid + ")", e); + } +- } catch (AttachNotSupportedException | IOException | AgentLoadException | AgentInitializationException e) { +- throw new RemoteException("Failed to attach to VM", e); + } + } + +- boolean isAttached(Subject user) throws RemoteException, SecurityException { +- authCheck(user); ++ boolean isAttached() { + return attached; + } + +- String getConnectorAddress(Subject user) throws RemoteException, SecurityException { +- authCheck(user); ++ String getConnectorAddress() throws IOException { + if (!attached) { +- throw new RemoteException("Agent not attached to target VM"); ++ throw new IOException("Agent not attached to target VM"); + } + return connectorAddress; + } + +- void detach(Subject user) throws RemoteException, SecurityException { +- authCheck(user); +- try { +- if (attached) { +- vm.detach(); +- attached = false; +- } +- } catch (IOException e) { +- throw new RemoteException("Failed to detach from VM", e); +- } +- } +- +- private void authCheck(Subject user) throws SecurityException { +- // If we've added our Principal, we've authenticated this user +- Set principals = user.getPrincipals(AgentProxyPrincipal.class); +- if (principals.isEmpty()) { +- throw new SecurityException("Access Denied"); ++ void detach() throws IOException { ++ if (attached) { ++ vm.detach(); ++ attached = false; + } + } + +diff -urN thermostat-1.0.4.old/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyControlWrapper.java thermostat-1.0.4/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyControlWrapper.java +--- thermostat-1.0.4.old/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyControlWrapper.java 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyControlWrapper.java 1969-12-31 19:00:00.000000000 -0500 +@@ -1,97 +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 +- * . +- * +- * 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.proxy.server; +- +-import java.rmi.RemoteException; +- +-import javax.security.auth.Subject; +-import javax.security.auth.login.LoginException; +- +-import com.redhat.thermostat.agent.proxy.common.AgentProxyControl; +- +-class AgentProxyControlWrapper implements AgentProxyControl { +- +- private final Subject user; +- private final AgentProxyLoginContext context; +- private final AgentProxyControlImpl impl; +- private final ShutdownListener listener; +- private final RegistryUtils registryUtils; +- +- AgentProxyControlWrapper(Subject user, AgentProxyLoginContext context, AgentProxyControlImpl impl, +- ShutdownListener listener, RegistryUtils registryUtils) { +- this.user = user; +- this.context = context; +- this.impl = impl; +- this.listener = listener; +- this.registryUtils = registryUtils; +- } +- +- @Override +- public void attach() throws RemoteException, SecurityException { +- impl.attach(user); +- } +- +- @Override +- public boolean isAttached() throws RemoteException, SecurityException { +- return impl.isAttached(user); +- } +- +- @Override +- public String getConnectorAddress() throws RemoteException, SecurityException { +- return impl.getConnectorAddress(user); +- } +- +- @Override +- public void detach() throws RemoteException, SecurityException { +- try { +- impl.detach(user); +- } finally { +- try { +- // Removes all Principals +- context.logout(); +- } catch (LoginException e) { +- throw new RemoteException("Failed to log out", e); +- } +- // Unexport this object +- registryUtils.unexportObject(this); +- +- // Shutdown RMI server +- listener.shutdown(); +- } +- } +- +-} +diff -urN thermostat-1.0.4.old/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxy.java thermostat-1.0.4/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxy.java +--- thermostat-1.0.4.old/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxy.java 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxy.java 2014-12-05 14:26:44.824484006 -0500 +@@ -37,50 +37,21 @@ + package com.redhat.thermostat.agent.proxy.server; + + import java.io.IOException; +-import java.rmi.NotBoundException; +-import java.rmi.RemoteException; +-import java.rmi.registry.Registry; +-import java.util.Timer; +-import java.util.TimerTask; ++import java.io.PrintStream; + import java.util.logging.Level; + import java.util.logging.Logger; + +-import com.redhat.thermostat.agent.proxy.common.AgentProxyListener; +-import com.redhat.thermostat.agent.proxy.common.AgentProxyLogin; + import com.redhat.thermostat.common.utils.LoggingUtils; ++import com.sun.tools.attach.AttachNotSupportedException; + + public class AgentProxy { + + private static final Logger logger = LoggingUtils.getLogger(AgentProxy.class); +- private static final long TIMEOUT_MS = 300000L; // 5 minutes should be more than enough +- private static final ShutdownListener shutdownListener = new ShutdownListener() { +- @Override +- public void shutdown() throws RemoteException { +- shutdownProxy(); +- } +- }; +- private static final TimerTask timeoutTask = new TimerTask() { +- @Override +- public void run() { +- try { +- shutdownProxy(); +- logger.warning("Server timed out"); +- } catch (RemoteException e) { +- logger.log(Level.SEVERE, "Exception while shutting down " +- + "timed out server" , e); +- } +- } +- }; +- +- private static String name = null; ++ + private static int pid = -1; +- private static Registry registry = null; +- private static boolean bound = false; +- private static AgentProxyLogin agent = null; +- private static RegistryUtils registryUtils = new RegistryUtils(); +- private static AgentProxyNativeUtils nativeUtils = new AgentProxyNativeUtils(); +- private static ProcessUserInfoBuilder builder = new ProcessUserInfoBuilder(new ProcDataSource()); +- private static Timer timeoutTimer = new Timer(true); ++ private static AgentProxyControlImpl agent = null; ++ private static ControlCreator creator = new ControlCreator(); ++ private static PrintStream outStream = System.out; + + public static void main(String[] args) { + if (args.length < 1) { +@@ -94,87 +65,27 @@ + usage(); + } + +- // Schedule a timeout +- timeoutTimer.schedule(timeoutTask, TIMEOUT_MS); +- +- // Load the native library +- nativeUtils.loadLibrary(); +- +- // Look for registered status listener +- AgentProxyListener listener; +- try { +- String listenerName = AgentProxyListener.REMOTE_PREFIX + String.valueOf(pid); +- registry = registryUtils.getRegistry(); +- listener = (AgentProxyListener) registry.lookup(listenerName); +- } catch (RemoteException e) { +- throw new RuntimeException("Failed to locate registry", e); +- } catch (NotBoundException e) { +- throw new RuntimeException("No listener registered", e); +- } +- + // Start proxy agent +- Exception ex = null; ++ agent = creator.create(pid); ++ + try { +- setupProxy(pid); +- } catch (Exception e) { +- logger.log(Level.SEVERE, "Failed to setup agent proxy for " + pid, e); +- ex = e; ++ agent.attach(); ++ } catch (AttachNotSupportedException | IOException e) { ++ logger.log(Level.SEVERE, "Failed to attach to VM (pid: " + pid + ")", e); ++ return; + } + +- // Notify listener of result + try { +- if (ex == null) { +- // Success +- listener.serverStarted(); +- } +- else { +- // Send exception to client +- listener.serverFailedToStart(ex); +- } +- } catch (RemoteException e) { +- throw new RuntimeException("Failed to notify listener", e); ++ String connectorAddress = agent.getConnectorAddress(); ++ outStream.println(connectorAddress); ++ } catch (IOException e) { ++ logger.log(Level.SEVERE, "Failed to retrieve JMX connection URL", e); + } +- } +- +- private static void setupProxy(int pid) throws Exception { ++ + try { +- UnixCredentials creds; +- try { +- creds = builder.build(pid); +- } catch (IOException e) { +- throw new Exception("Failed to read credentials", e); +- } +- +- try { +- // Set UID/GID to owner of target VM +- nativeUtils.setCredentials(creds.getUid(), creds.getGid()); +- } catch (Exception e) { +- throw new Exception("Failed to set credentials to " + creds.getUid() +- + ":" + creds.getGid() , e); +- } +- +- agent = new AgentProxyLoginImpl(creds, pid, shutdownListener); +- name = AgentProxyLogin.REMOTE_PREFIX + String.valueOf(pid); +- AgentProxyLogin stub = (AgentProxyLogin) registryUtils.exportObject(agent); +- registry.rebind(name, stub); +- bound = true; +- logger.info(name + " bound to RMI registry"); +- } catch (RemoteException e) { +- throw new Exception("Failed to create remote object", e); +- } +- } +- +- private static void shutdownProxy() throws RemoteException { +- // Unbind from RMI registry +- if (bound) { +- try { +- registry.unbind(name); +- registryUtils.unexportObject(agent); +- logger.info(name + " unbound from RMI registry"); +- bound = false; +- } catch (NotBoundException e) { +- throw new RemoteException("Object not bound", e); +- } ++ agent.detach(); ++ } catch (IOException e) { ++ logger.log(Level.WARNING, "Failed to detach from VM (pid: " + pid + ")", e); + } + } + +@@ -182,52 +93,24 @@ + throw new RuntimeException("usage: java " + AgentProxy.class.getName() + " "); + } + +- /* +- * For testing purposes only. +- */ +- static AgentProxyLogin getAgentProxyLogin() { +- return agent; +- } +- +- /* +- * For testing purposes only. +- */ +- static ShutdownListener getShutdownListener() { +- return shutdownListener; +- } +- +- /* +- * For testing purposes only. +- */ +- static boolean isBound() { +- return bound; +- } +- +- /* +- * For testing purposes only. +- */ +- static void setRegistryUtils(RegistryUtils registryUtils) { +- AgentProxy.registryUtils = registryUtils; ++ static class ControlCreator { ++ AgentProxyControlImpl create(int pid) { ++ return new AgentProxyControlImpl(pid); ++ } + } + + /* + * For testing purposes only. + */ +- static void setNativeUtils(AgentProxyNativeUtils nativeUtils) { +- AgentProxy.nativeUtils = nativeUtils; ++ static void setControlCreator(ControlCreator creator) { ++ AgentProxy.creator = creator; + } + + /* + * For testing purposes only. + */ +- static void setProcessUserInfoBuilder(ProcessUserInfoBuilder builder) { +- AgentProxy.builder = builder; ++ static void setOutStream(PrintStream stream) { ++ AgentProxy.outStream = stream; + } + +- /* +- * For testing purposes only. +- */ +- static void setTimeoutTimer(Timer timeoutTimer) { +- AgentProxy.timeoutTimer = timeoutTimer; +- } + } +diff -urN thermostat-1.0.4.old/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginContext.java thermostat-1.0.4/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginContext.java +--- thermostat-1.0.4.old/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginContext.java 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginContext.java 1969-12-31 19:00:00.000000000 -0500 +@@ -1,101 +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 +- * . +- * +- * 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.proxy.server; +- +-import java.io.IOException; +- +-import javax.security.auth.Subject; +-import javax.security.auth.callback.Callback; +-import javax.security.auth.callback.CallbackHandler; +-import javax.security.auth.callback.UnsupportedCallbackException; +-import javax.security.auth.login.LoginContext; +-import javax.security.auth.login.LoginException; +- +-import com.redhat.thermostat.agent.proxy.server.AgentProxyLoginModule.AgentProxyCallback; +- +-/* +- * Wraps both of our LoginModules. +- */ +-class AgentProxyLoginContext { +- +- private static final String UNIX_LOGIN_MODULE = "UnixLogin"; +- private static final String AGENT_PROXY_LOGIN_MODULE = "AgentProxyLogin"; +- +- private final LoginContext unixContext; +- private final LoginContext context; +- +- AgentProxyLoginContext(Subject user, UnixCredentials creds) throws LoginException { +- this(user, creds, new ContextCreator()); +- } +- +- AgentProxyLoginContext(Subject user, final UnixCredentials creds, ContextCreator creator) throws LoginException { +- unixContext = creator.createContext(UNIX_LOGIN_MODULE, user); +- context = creator.createContext(AGENT_PROXY_LOGIN_MODULE, user, new CallbackHandler() { +- +- @Override +- public void handle(Callback[] callbacks) throws IOException, +- UnsupportedCallbackException { +- for (Callback callback : callbacks) { +- if (callback instanceof AgentProxyCallback) { +- ((AgentProxyCallback) callback).setTargetCredentials(creds); +- } +- } +- } +- }); +- } +- +- void login() throws LoginException { +- unixContext.login(); +- context.login(); +- } +- +- void logout() throws LoginException { +- context.logout(); +- unixContext.logout(); +- } +- +- static class ContextCreator { +- LoginContext createContext(String name, Subject subject) throws LoginException { +- return new LoginContext(name, subject); +- } +- +- LoginContext createContext(String name, Subject subject, CallbackHandler handler) throws LoginException { +- return new LoginContext(name, subject, handler); +- } +- } +- +-} +diff -urN thermostat-1.0.4.old/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginImpl.java thermostat-1.0.4/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginImpl.java +--- thermostat-1.0.4.old/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginImpl.java 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginImpl.java 1969-12-31 19:00:00.000000000 -0500 +@@ -1,90 +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 +- * . +- * +- * 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.proxy.server; +- +-import java.rmi.RemoteException; +- +-import javax.security.auth.Subject; +-import javax.security.auth.login.LoginException; +- +-import com.redhat.thermostat.agent.proxy.common.AgentProxyControl; +-import com.redhat.thermostat.agent.proxy.common.AgentProxyLogin; +- +-class AgentProxyLoginImpl implements AgentProxyLogin { +- +- private final UnixCredentials creds; +- private final AgentProxyControlImpl impl; +- private final ShutdownListener listener; +- private final LoginContextCreator contextCreator; +- private final RegistryUtils registryUtils; +- +- AgentProxyLoginImpl(UnixCredentials creds, int pid, ShutdownListener listener) throws RemoteException { +- this(creds, pid, listener, new LoginContextCreator(), new RegistryUtils()); +- } +- +- AgentProxyLoginImpl(UnixCredentials creds, int pid, ShutdownListener listener, +- LoginContextCreator contextCreator, RegistryUtils registryUtils) throws RemoteException { +- this.creds = creds; +- this.impl = new AgentProxyControlImpl(pid); +- this.listener = listener; +- this.contextCreator = contextCreator; +- this.registryUtils = registryUtils; +- } +- +- @Override +- public AgentProxyControl login() throws RemoteException, SecurityException { +- Subject user = new Subject(); +- try { +- AgentProxyLoginContext context = contextCreator.createContext(user, creds); +- context.login(); +- +- AgentProxyControl control = new AgentProxyControlWrapper(user, context, impl, +- listener, registryUtils); +- AgentProxyControl stub = (AgentProxyControl) registryUtils.exportObject(control); +- return stub; +- } catch (LoginException e) { +- throw new RemoteException("Failed to login", e); +- } +- } +- +- static class LoginContextCreator { +- AgentProxyLoginContext createContext(Subject user, UnixCredentials creds) throws LoginException { +- return new AgentProxyLoginContext(user, creds); +- } +- } +- +-} +diff -urN thermostat-1.0.4.old/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginModule.java thermostat-1.0.4/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginModule.java +--- thermostat-1.0.4.old/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginModule.java 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginModule.java 1969-12-31 19:00:00.000000000 -0500 +@@ -1,239 +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 +- * . +- * +- * 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.proxy.server; +- +-import java.io.IOException; +-import java.util.Map; +-import java.util.Set; +-import java.util.concurrent.CountDownLatch; +- +-import javax.security.auth.Subject; +-import javax.security.auth.callback.Callback; +-import javax.security.auth.callback.CallbackHandler; +-import javax.security.auth.callback.UnsupportedCallbackException; +-import javax.security.auth.login.LoginException; +-import javax.security.auth.spi.LoginModule; +- +-public class AgentProxyLoginModule implements LoginModule { +- +- private Subject subject; +- private CallbackHandler callbackHandler; +- private AgentProxyPrincipal principal; +- private boolean loggedIn; +- private boolean committed; +- private boolean debug; +- +- interface AgentProxyCallback extends Callback { +- +- void setTargetCredentials(UnixCredentials creds); +- +- } +- +- @Override +- public void initialize(Subject subject, CallbackHandler callbackHandler, +- Map sharedState, Map options) { +- this.subject = subject; +- this.callbackHandler = callbackHandler; +- +- // Check for debug option +- debug = "true".equalsIgnoreCase((String) options.get("debug")); +- } +- +- @Override +- public boolean login() throws LoginException { +- loggedIn = false; +- +- // Get credentials of target process from callback +- UnixCredentials creds = getTargetCredentials(); +- +- // Verify subject's credentials match those of target process +- checkCredentials(creds); +- +- // Add a custom principal to the subject to show we've authenticated +- principal = createPrincipal(); +- if (debug) { +- System.out.println("\t\t[AgentProxyLoginModule]: " + +- "created principal for user: " + principal.getName()); +- } +- +- loggedIn = true; +- return true; +- } +- +- private UnixCredentials getTargetCredentials() throws LoginException { +- final CountDownLatch latch = new CountDownLatch(1); +- final UnixCredentials[] credsContainer = new UnixCredentials[1]; +- +- try { +- callbackHandler.handle(new Callback[] { new AgentProxyCallback() { +- +- @Override +- public void setTargetCredentials(UnixCredentials creds) { +- credsContainer[0] = creds; +- latch.countDown(); +- } +- +- }}); +- +- latch.await(); +- +- return credsContainer[0]; +- } catch (IOException e) { +- throw new LoginException(e.getMessage()); +- } catch (UnsupportedCallbackException e) { +- throw new LoginException(e.getMessage()); +- } catch (InterruptedException e) { +- throw new LoginException("Interrupted"); +- } +- } +- +- @Override +- public boolean commit() throws LoginException { +- committed = false; +- +- if (loggedIn) { +- subject.getPrincipals().add(principal); +- if (debug) { +- System.out.println("\t\t[AgentProxyLoginModule]: " + +- "adding AgentProxyPrincipal to Subject"); +- } +- committed = true; +- } +- return committed; +- } +- +- @Override +- public boolean abort() throws LoginException { +- if (debug) { +- System.out.println("\t\t[AgentProxyLoginModule]: " + +- "aborted authentication attempt"); +- } +- if (!loggedIn) { +- return false; +- } +- else if (loggedIn && !committed) { +- // Clean up state +- loggedIn = false; +- principal = null; +- } +- else { +- // Clean up state & remove principal +- logout(); +- } +- +- return true; +- } +- +- @Override +- public boolean logout() throws LoginException { +- // Remove principal +- subject.getPrincipals().remove(principal); +- if (debug) { +- System.out.println("\t\t[AgentProxyLoginModule]: " + +- "removed principal for user: " + principal.getName()); +- } +- +- // Clean up state +- loggedIn = false; +- committed = false; +- principal = null; +- +- return true; +- } +- +- @SuppressWarnings("restriction") +- private void checkCredentials(UnixCredentials creds) throws LoginException { +- boolean uidOkay = false, gidOkay = false; +- +- // Check UID +- Set userPrincipals = subject.getPrincipals(com.sun.security.auth.UnixNumericUserPrincipal.class); +- if (!userPrincipals.isEmpty()) { +- com.sun.security.auth.UnixNumericUserPrincipal userPrincipal = userPrincipals.iterator().next(); +- if (debug) { +- System.out.println("UnixLoginModule UID: " + userPrincipal.longValue() + ", PID: " + creds.getPid() + ", Owner: " + creds.getUid()); +- } +- if (userPrincipal.longValue() == creds.getUid() || userPrincipal.longValue() == 0) { +- uidOkay = true; +- } +- } +- +- // Check GID +- Set groupPrincipals = subject.getPrincipals(com.sun.security.auth.UnixNumericGroupPrincipal.class); +- for (com.sun.security.auth.UnixNumericGroupPrincipal groupPrincipal : groupPrincipals) { +- if (groupPrincipal.longValue() == creds.getGid() || groupPrincipal.longValue() == 0) { +- gidOkay = true; +- } +- } +- +- if (!uidOkay || !gidOkay) { +- throw new LoginException("Access Denied"); +- } +- } +- +- @SuppressWarnings("restriction") +- private AgentProxyPrincipal createPrincipal() throws LoginException { +- Set userPrincipals = subject.getPrincipals(com.sun.security.auth.UnixPrincipal.class); +- if (userPrincipals.isEmpty()) { +- throw new LoginException("Unable to obtain user ID"); +- } +- +- com.sun.security.auth.UnixPrincipal userPrincipal = userPrincipals.iterator().next(); +- return new AgentProxyPrincipal(userPrincipal.getName()); +- } +- +- /* +- * For testing purposes only. +- */ +- AgentProxyPrincipal getPrincipal() { +- return principal; +- } +- +- /* +- * For testing purposes only. +- */ +- boolean isLoggedIn() { +- return loggedIn; +- } +- +- /* +- * For testing purposes only. +- */ +- boolean isCommitted() { +- return committed; +- } +- +-} +diff -urN thermostat-1.0.4.old/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyNativeUtils.java thermostat-1.0.4/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyNativeUtils.java +--- thermostat-1.0.4.old/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyNativeUtils.java 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyNativeUtils.java 1969-12-31 19:00:00.000000000 -0500 +@@ -1,53 +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 +- * . +- * +- * 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.proxy.server; +- +-import com.redhat.thermostat.shared.config.NativeLibraryResolver; +-import com.redhat.thermostat.shared.config.internal.CommonPathsImpl; +- +-class AgentProxyNativeUtils { +- +- void loadLibrary() { +- // TODO if this used OSGi, then we wouldn't need this line +- NativeLibraryResolver.setCommonPaths(new CommonPathsImpl()); +- String libPath = NativeLibraryResolver.getAbsoluteLibraryPath("AgentProxy"); +- System.load(libPath); +- } +- +- native void setCredentials(long uid, long gid) throws Exception; +- +-} +diff -urN thermostat-1.0.4.old/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyPrincipal.java thermostat-1.0.4/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyPrincipal.java +--- thermostat-1.0.4.old/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyPrincipal.java 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyPrincipal.java 1969-12-31 19:00:00.000000000 -0500 +@@ -1,54 +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 +- * . +- * +- * 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.proxy.server; +- +-import java.security.Principal; +- +-class AgentProxyPrincipal implements Principal { +- +- private final String name; +- +- AgentProxyPrincipal(String name) { +- this.name = name; +- } +- +- @Override +- public String getName() { +- return name; +- } +- +-} +diff -urN thermostat-1.0.4.old/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/ProcDataSource.java thermostat-1.0.4/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/ProcDataSource.java +--- thermostat-1.0.4.old/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/ProcDataSource.java 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/ProcDataSource.java 1969-12-31 19:00:00.000000000 -0500 +@@ -1,63 +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 +- * . +- * +- * 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.proxy.server; +- +-import java.io.FileReader; +-import java.io.IOException; +-import java.io.Reader; +- +-/** +- * Wrapper for files under /proc. See proc(5) for details about this. +- */ +-class ProcDataSource { +- +- private static final String PID_STATUS_FILE = "/proc/${pid}/status"; +- +- /** +- * Returns a reader for /proc/$PID/status +- */ +- Reader getStatusReader(int pid) throws IOException { +- return new FileReader(getPidFile(PID_STATUS_FILE, pid)); +- } +- +- private String getPidFile(String fileName, int pid) { +- return fileName.replace("${pid}", Integer.toString(pid)); +- } +- +-} +- +- +diff -urN thermostat-1.0.4.old/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/ProcessUserInfoBuilder.java thermostat-1.0.4/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/ProcessUserInfoBuilder.java +--- thermostat-1.0.4.old/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/ProcessUserInfoBuilder.java 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/ProcessUserInfoBuilder.java 1969-12-31 19:00:00.000000000 -0500 +@@ -1,105 +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 +- * . +- * +- * 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.proxy.server; +- +-import java.io.BufferedReader; +-import java.io.IOException; +-import java.io.Reader; +- +-class ProcessUserInfoBuilder { +- +- private static final String PROC_STATUS_UID = "Uid:"; +- private static final String PROC_STATUS_GID = "Gid:"; +- +- private final ProcDataSource source; +- +- ProcessUserInfoBuilder(ProcDataSource source) { +- this.source = source; +- } +- +- UnixCredentials build(int pid) throws IOException { +- Reader reader = source.getStatusReader(pid); +- UnixCredentials creds = getUidGidFromProcfs(new BufferedReader(reader), pid); +- return creds; +- } +- +- /* +- * Look for the following lines: +- * Uid: +- * Gid: +- */ +- private UnixCredentials getUidGidFromProcfs(BufferedReader br, int pid) throws IOException { +- long uid = -1; +- long gid = -1; +- String line; +- while ((line = br.readLine()) != null) { +- line = line.trim(); +- if (line.startsWith(PROC_STATUS_UID)) { +- uid = parseUidGid(line); +- } +- else if (line.startsWith(PROC_STATUS_GID)) { +- gid = parseUidGid(line); +- } +- } +- if (uid < 0) { +- throw new IOException("Unable to determine UID from /proc/${pid}/status"); +- } +- if (gid < 0) { +- throw new IOException("Unable to determine GID from /proc/${pid}/status"); +- } +- +- return new UnixCredentials(uid, gid, pid); +- } +- +- private long parseUidGid(String line) throws IOException { +- long result = -1; +- String[] parts = line.split("\\s+"); +- if (parts.length == 5) { +- try { +- // Use Effective UID/GID +- result = Long.parseLong(parts[2]); +- } catch (NumberFormatException e) { +- throw new IOException("Unexpected output from ps command", e); +- } +- } +- else { +- throw new IOException("Expected 5 parts from split /proc/${pid}/status output, got " + parts.length); +- } +- return result; +- } +- +-} +diff -urN thermostat-1.0.4.old/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/RegistryUtils.java thermostat-1.0.4/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/RegistryUtils.java +--- thermostat-1.0.4.old/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/RegistryUtils.java 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/RegistryUtils.java 1969-12-31 19:00:00.000000000 -0500 +@@ -1,26 +0,0 @@ +-package com.redhat.thermostat.agent.proxy.server; +- +-import java.net.InetAddress; +-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.UnicastRemoteObject; +- +-class RegistryUtils { +- +- Registry getRegistry() throws RemoteException { +- return LocateRegistry.getRegistry(InetAddress.getLoopbackAddress().getHostName()); +- } +- +- Remote exportObject(Remote obj) throws RemoteException { +- // Single arg method exports stub instead of real object +- return UnicastRemoteObject.exportObject(obj, 0); +- } +- +- void unexportObject(Remote obj) throws NoSuchObjectException { +- UnicastRemoteObject.unexportObject(obj, true); +- } +- +-} +\ No newline at end of file +diff -urN thermostat-1.0.4.old/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/ShutdownListener.java thermostat-1.0.4/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/ShutdownListener.java +--- thermostat-1.0.4.old/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/ShutdownListener.java 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/ShutdownListener.java 1969-12-31 19:00:00.000000000 -0500 +@@ -1,45 +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 +- * . +- * +- * 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.proxy.server; +- +-import java.rmi.RemoteException; +- +-interface ShutdownListener { +- +- void shutdown() throws RemoteException; +- +-} +diff -urN thermostat-1.0.4.old/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/UnixCredentials.java thermostat-1.0.4/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/UnixCredentials.java +--- thermostat-1.0.4.old/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/UnixCredentials.java 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/UnixCredentials.java 1969-12-31 19:00:00.000000000 -0500 +@@ -1,63 +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 +- * . +- * +- * 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.proxy.server; +- +-class UnixCredentials { +- +- private final long uid; +- private final long gid; +- private final int pid; +- +- UnixCredentials(long uid, long gid, int pid) { +- this.uid = uid; +- this.gid = gid; +- this.pid = pid; +- } +- +- long getUid() { +- return uid; +- } +- +- long getGid() { +- return gid; +- } +- +- int getPid() { +- return pid; +- } +- +-} +\ No newline at end of file +diff -urN thermostat-1.0.4.old/agent/proxy/server/src/main/native/AgentProxy.c thermostat-1.0.4/agent/proxy/server/src/main/native/AgentProxy.c +--- thermostat-1.0.4.old/agent/proxy/server/src/main/native/AgentProxy.c 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/proxy/server/src/main/native/AgentProxy.c 1969-12-31 19:00:00.000000000 -0500 +@@ -1,75 +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 +- * . +- * +- * 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. +- */ +- +-#include "com_redhat_thermostat_agent_proxy_server_AgentProxyNativeUtils.h" +- +-#include +-#include +-#include +- +-static jint throw_Exception(JNIEnv *, const char *, const char *); +- +-JNIEXPORT void JNICALL +-Java_com_redhat_thermostat_agent_proxy_server_AgentProxyNativeUtils_setCredentials( +- JNIEnv *env, jclass splitAgentKlass, jlong uid, jlong gid) { +- int rc; +- char *err; +- +- // Need to setegid before seteuid, or otherwise we've dropped permissions +- // needed to do so. +- rc = setegid(gid); +- if (rc < 0) { +- err = strerror(errno); +- throw_Exception(env, "java/lang/Exception", err); +- } +- +- rc = seteuid(uid); +- if (rc < 0) { +- err = strerror(errno); +- throw_Exception(env, "java/lang/Exception", err); +- } +-} +- +-static jint throw_Exception(JNIEnv *env, const char *class_name, +- const char *message) { +- jclass class; +- +- class = (*env)->FindClass(env, class_name); +- if (class == NULL) { +- return -1; +- } +- return (*env)->ThrowNew(env, class, message); +-} +diff -urN thermostat-1.0.4.old/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyControlImplTest.java thermostat-1.0.4/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyControlImplTest.java +--- thermostat-1.0.4.old/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyControlImplTest.java 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyControlImplTest.java 2014-12-05 14:26:44.829484036 -0500 +@@ -47,11 +47,9 @@ + import static org.mockito.Mockito.when; + + import java.io.File; +-import java.rmi.RemoteException; ++import java.io.IOException; + import java.util.Properties; + +-import javax.security.auth.Subject; +- + import org.junit.Before; + import org.junit.Test; + +@@ -84,9 +82,7 @@ + + @Test + public void testAttach() throws Exception { +- Subject subject = new Subject(); +- addPrincipal(subject); +- control.attach(subject); ++ control.attach(); + + verify(vmUtils).attach("0"); + verify(vm, times(2)).getAgentProperties(); +@@ -94,79 +90,36 @@ + verify(vm).loadAgent("/path/to/java/home" + File.separator + "lib" + File.separator + "management-agent.jar"); + } + +- @Test(expected=SecurityException.class) +- public void testAttachDenied() throws Exception { +- Subject subject = new Subject(); +- control.attach(subject); +- } +- + @Test + public void testIsAttached() throws Exception { +- Subject subject = new Subject(); +- addPrincipal(subject); +- +- assertFalse(control.isAttached(subject)); +- control.attach(subject); +- assertTrue(control.isAttached(subject)); +- } +- +- @Test(expected=SecurityException.class) +- public void testIsAttachedDenied() throws Exception { +- Subject subject = new Subject(); +- control.isAttached(subject); ++ assertFalse(control.isAttached()); ++ control.attach(); ++ assertTrue(control.isAttached()); + } + + @Test + public void testGetAddress() throws Exception { +- Subject subject = new Subject(); +- addPrincipal(subject); +- +- control.attach(subject); +- String addr = control.getConnectorAddress(subject); ++ control.attach(); ++ String addr = control.getConnectorAddress(); + assertEquals("myJmxUrl", addr); + } + +- @Test(expected=SecurityException.class) +- public void testGetAddressDenied() throws Exception { +- Subject subject = new Subject(); +- control.getConnectorAddress(subject); +- } +- +- @Test(expected=RemoteException.class) ++ @Test(expected=IOException.class) + public void testGetAddressNotAttached() throws Exception { +- Subject subject = new Subject(); +- addPrincipal(subject); +- +- control.getConnectorAddress(subject); ++ control.getConnectorAddress(); + } + + @Test + public void testDetach() throws Exception { +- Subject subject = new Subject(); +- addPrincipal(subject); +- +- control.attach(subject); +- control.detach(subject); ++ control.attach(); ++ control.detach(); + verify(vm).detach(); + } + + @Test + public void testDetachNotAttached() throws Exception { +- Subject subject = new Subject(); +- addPrincipal(subject); +- +- control.detach(subject); ++ control.detach(); + verify(vm, never()).detach(); + } + +- @Test(expected=SecurityException.class) +- public void testDetachDenied() throws Exception { +- Subject subject = new Subject(); +- control.detach(subject); +- } +- +- private void addPrincipal(Subject subject) { +- subject.getPrincipals().add(new AgentProxyPrincipal("TEST")); +- } +- + } +diff -urN thermostat-1.0.4.old/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyControlWrapperTest.java thermostat-1.0.4/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyControlWrapperTest.java +--- thermostat-1.0.4.old/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyControlWrapperTest.java 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyControlWrapperTest.java 1969-12-31 19:00:00.000000000 -0500 +@@ -1,94 +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 +- * . +- * +- * 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.proxy.server; +- +-import static org.mockito.Mockito.mock; +-import static org.mockito.Mockito.verify; +- +-import javax.security.auth.Subject; +- +-import org.junit.Before; +-import org.junit.Test; +- +-public class AgentProxyControlWrapperTest { +- +- private AgentProxyControlWrapper control; +- private AgentProxyControlImpl impl; +- private Subject user; +- private AgentProxyLoginContext context; +- private ShutdownListener listener; +- private RegistryUtils registryUtils; +- +- @Before +- public void setup() throws Exception { +- user = new Subject(); +- context = mock(AgentProxyLoginContext.class); +- impl = mock(AgentProxyControlImpl.class); +- listener = mock(ShutdownListener.class); +- registryUtils = mock(RegistryUtils.class); +- control = new AgentProxyControlWrapper(user, context, impl, listener, registryUtils); +- } +- +- @Test +- public void testAttach() throws Exception { +- control.attach(); +- verify(impl).attach(user); +- } +- +- @Test +- public void testIsAttached() throws Exception { +- control.isAttached(); +- verify(impl).isAttached(user); +- } +- +- @Test +- public void testGetAddress() throws Exception { +- control.getConnectorAddress(); +- verify(impl).getConnectorAddress(user); +- } +- +- @Test +- public void testDetach() throws Exception { +- control.detach(); +- +- verify(impl).detach(user); +- verify(context).logout(); +- verify(listener).shutdown(); +- verify(registryUtils).unexportObject(control); +- } +- +-} +diff -urN thermostat-1.0.4.old/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginContextTest.java thermostat-1.0.4/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginContextTest.java +--- thermostat-1.0.4.old/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginContextTest.java 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginContextTest.java 1969-12-31 19:00:00.000000000 -0500 +@@ -1,105 +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 +- * . +- * +- * 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.proxy.server; +- +-import static org.mockito.Matchers.any; +-import static org.mockito.Matchers.eq; +-import static org.mockito.Matchers.same; +-import static org.mockito.Mockito.mock; +-import static org.mockito.Mockito.verify; +-import static org.mockito.Mockito.when; +- +-import javax.security.auth.Subject; +-import javax.security.auth.callback.Callback; +-import javax.security.auth.callback.CallbackHandler; +-import javax.security.auth.login.LoginContext; +- +-import org.junit.Before; +-import org.junit.Test; +-import org.mockito.ArgumentCaptor; +- +-import com.redhat.thermostat.agent.proxy.server.AgentProxyLoginContext.ContextCreator; +-import com.redhat.thermostat.agent.proxy.server.AgentProxyLoginModule.AgentProxyCallback; +- +-public class AgentProxyLoginContextTest { +- +- private AgentProxyLoginContext context; +- private ContextCreator creator; +- private Subject user; +- private UnixCredentials creds; +- private LoginContext unixContext; +- private LoginContext ourContext; +- +- @Before +- public void setup() throws Exception { +- user = new Subject(); +- creds = new UnixCredentials(9000, 9001, 0); +- creator = mock(ContextCreator.class); +- unixContext = mock(LoginContext.class); +- ourContext = mock(LoginContext.class); +- when(creator.createContext("UnixLogin", user)).thenReturn(unixContext); +- when(creator.createContext(eq("AgentProxyLogin"), same(user), any(CallbackHandler.class))).thenReturn(ourContext); +- context = new AgentProxyLoginContext(user, creds, creator); +- } +- +- @Test +- public void testCreate() throws Exception { +- verify(creator).createContext("UnixLogin", user); +- ArgumentCaptor captor = ArgumentCaptor.forClass(CallbackHandler.class); +- verify(creator).createContext(eq("AgentProxyLogin"), same(user), captor.capture()); +- CallbackHandler handler = captor.getValue(); +- +- AgentProxyCallback callback = mock(AgentProxyCallback.class); +- handler.handle(new Callback[] { callback }); +- verify(callback).setTargetCredentials(creds); +- } +- +- @Test +- public void testLogin() throws Exception { +- context.login(); +- verify(unixContext).login(); +- verify(ourContext).login(); +- } +- +- @Test +- public void testLogout() throws Exception { +- context.logout(); +- verify(ourContext).logout(); +- verify(unixContext).logout(); +- } +- +-} +diff -urN thermostat-1.0.4.old/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginImplTest.java thermostat-1.0.4/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginImplTest.java +--- thermostat-1.0.4.old/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginImplTest.java 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginImplTest.java 1969-12-31 19:00:00.000000000 -0500 +@@ -1,117 +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 +- * . +- * +- * 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.proxy.server; +- +-import static org.junit.Assert.assertEquals; +-import static org.junit.Assert.assertFalse; +-import static org.junit.Assert.assertTrue; +-import static org.junit.Assert.fail; +-import static org.mockito.Matchers.any; +-import static org.mockito.Matchers.same; +-import static org.mockito.Mockito.doThrow; +-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.rmi.RemoteException; +-import java.rmi.registry.Registry; +- +-import javax.security.auth.Subject; +-import javax.security.auth.login.LoginException; +- +-import org.junit.Before; +-import org.junit.Test; +-import org.mockito.ArgumentCaptor; +- +-import com.redhat.thermostat.agent.proxy.common.AgentProxyControl; +-import com.redhat.thermostat.agent.proxy.server.AgentProxyLoginImpl.LoginContextCreator; +- +-public class AgentProxyLoginImplTest { +- +- private RegistryUtils registryUtils; +- private Registry registry; +- private UnixCredentials creds; +- private LoginContextCreator contextCreator; +- private AgentProxyLoginContext context; +- +- @Before +- public void setup() throws Exception { +- registry = mock(Registry.class); +- registryUtils = mock(RegistryUtils.class); +- when(registryUtils.getRegistry()).thenReturn(registry); +- creds = new UnixCredentials(9000, 9001, 0); +- contextCreator = mock(LoginContextCreator.class); +- context = mock(AgentProxyLoginContext.class); +- when(contextCreator.createContext(any(Subject.class), same(creds))).thenReturn(context); +- } +- +- @Test +- public void testLoginSuccess() throws Exception { +- ShutdownListener listener = mock(ShutdownListener.class); +- AgentProxyLoginImpl proxyLogin = new AgentProxyLoginImpl(creds, 0, listener, contextCreator, registryUtils); +- AgentProxyControl stub = proxyLogin.login(); +- +- ArgumentCaptor captor = ArgumentCaptor.forClass(AgentProxyControl.class); +- verify(registryUtils).exportObject(captor.capture()); +- AgentProxyControl control = captor.getValue(); +- +- assertTrue(control instanceof AgentProxyControlWrapper); +- assertFalse(stub instanceof AgentProxyControlWrapper); +- } +- +- @Test +- public void testLoginFailure() throws Exception { +- ShutdownListener listener = mock(ShutdownListener.class); +- +- // Simulate login failure +- LoginException ex = new LoginException("TEST"); +- doThrow(ex).when(context).login(); +- +- AgentProxyLoginImpl proxyLogin = new AgentProxyLoginImpl(creds, 0, listener, contextCreator, registryUtils); +- +- try { +- proxyLogin.login(); +- fail("Expected exception from login"); +- } catch (RemoteException e) { +- assertEquals(ex, e.getCause()); +- } +- +- verify(registryUtils, never()).exportObject(any(AgentProxyControl.class)); +- } +- +-} +diff -urN thermostat-1.0.4.old/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginModuleTest.java thermostat-1.0.4/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginModuleTest.java +--- thermostat-1.0.4.old/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginModuleTest.java 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginModuleTest.java 1969-12-31 19:00:00.000000000 -0500 +@@ -1,246 +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 +- * . +- * +- * 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.proxy.server; +- +-import static org.junit.Assert.assertEquals; +-import static org.junit.Assert.assertFalse; +-import static org.junit.Assert.assertNotNull; +-import static org.junit.Assert.assertNull; +-import static org.junit.Assert.assertTrue; +-import static org.junit.Assert.fail; +-import static org.mockito.Mockito.*; +- +-import java.util.HashMap; +-import java.util.Set; +- +-import javax.security.auth.Subject; +-import javax.security.auth.callback.Callback; +-import javax.security.auth.callback.CallbackHandler; +-import javax.security.auth.login.LoginException; +- +-import org.junit.Before; +-import org.junit.Test; +-import org.mockito.invocation.InvocationOnMock; +-import org.mockito.stubbing.Answer; +- +-import com.redhat.thermostat.agent.proxy.server.AgentProxyLoginModule.AgentProxyCallback; +- +-public class AgentProxyLoginModuleTest { +- +- private AgentProxyLoginModule module; +- private CallbackHandler handler; +- private Subject subject; +- +- @Before +- public void setup() throws Exception { +- module = new AgentProxyLoginModule(); +- subject = new Subject(); +- handler = mock(CallbackHandler.class); +- final UnixCredentials creds = new UnixCredentials(9000, 9001, 0); +- doAnswer(new Answer() { +- @Override +- public Void answer(InvocationOnMock invocation) throws Throwable { +- Callback[] callbacks = (Callback[]) invocation.getArguments()[0]; +- for (Callback callback : callbacks) { +- if (callback instanceof AgentProxyCallback) { +- ((AgentProxyCallback) callback).setTargetCredentials(creds); +- } +- } +- return null; +- } +- }).when(handler).handle(any(Callback[].class)); +- module.initialize(subject, handler, new HashMap(), new HashMap()); +- } +- +- @Test +- public void testLoginSuccess() throws Exception { +- addPrincipals(); +- +- assertTrue(module.login()); +- +- AgentProxyPrincipal principal = module.getPrincipal(); +- assertNotNull(principal); +- assertEquals("TEST", principal.getName()); +- assertTrue(module.isLoggedIn()); +- assertFalse(module.isCommitted()); +- assertTrue(subject.getPrincipals(AgentProxyPrincipal.class).isEmpty()); +- } +- +- @SuppressWarnings("restriction") +- @Test +- public void testLoginBadUid() throws Exception { +- subject.getPrincipals().add(new com.sun.security.auth.UnixPrincipal("TEST")); +- subject.getPrincipals().add(new com.sun.security.auth.UnixNumericUserPrincipal(8000)); +- subject.getPrincipals().add(new com.sun.security.auth.UnixNumericGroupPrincipal(9001, true)); +- +- verifyFailedLogin(); +- } +- +- @SuppressWarnings("restriction") +- @Test +- public void testLoginMissingUid() throws Exception { +- subject.getPrincipals().add(new com.sun.security.auth.UnixPrincipal("TEST")); +- subject.getPrincipals().add(new com.sun.security.auth.UnixNumericGroupPrincipal(9001, true)); +- +- verifyFailedLogin(); +- } +- +- @SuppressWarnings("restriction") +- @Test +- public void testLoginBadGid() throws Exception { +- subject.getPrincipals().add(new com.sun.security.auth.UnixPrincipal("TEST")); +- subject.getPrincipals().add(new com.sun.security.auth.UnixNumericUserPrincipal(9000)); +- subject.getPrincipals().add(new com.sun.security.auth.UnixNumericGroupPrincipal(8001, true)); +- +- verifyFailedLogin(); +- } +- +- @SuppressWarnings("restriction") +- @Test +- public void testLoginMissingGid() throws Exception { +- subject.getPrincipals().add(new com.sun.security.auth.UnixPrincipal("TEST")); +- subject.getPrincipals().add(new com.sun.security.auth.UnixNumericUserPrincipal(9000)); +- +- verifyFailedLogin(); +- } +- +- @SuppressWarnings("restriction") +- @Test +- public void testLoginMissingUsername() throws Exception { +- subject.getPrincipals().add(new com.sun.security.auth.UnixNumericUserPrincipal(9000)); +- subject.getPrincipals().add(new com.sun.security.auth.UnixNumericGroupPrincipal(9001, true)); +- +- verifyFailedLogin(); +- } +- +- @Test +- public void testCommitSuccess() throws Exception { +- addPrincipals(); +- +- assertTrue(module.login()); +- assertTrue(module.commit()); +- +- assertTrue(module.isLoggedIn()); +- assertTrue(module.isCommitted()); +- Set principals = subject.getPrincipals(AgentProxyPrincipal.class); +- assertFalse(principals.isEmpty()); +- assertEquals(module.getPrincipal(), principals.iterator().next()); +- } +- +- @Test +- public void testCommitNotLoggedIn() throws Exception { +- addPrincipals(); +- +- assertFalse(module.commit()); +- +- assertFalse(module.isLoggedIn()); +- assertFalse(module.isCommitted()); +- assertTrue(subject.getPrincipals(AgentProxyPrincipal.class).isEmpty()); +- } +- +- @Test +- public void testAbortNotLoggedIn() throws Exception { +- addPrincipals(); +- +- assertFalse(module.abort()); +- +- verifyStateReset(); +- } +- +- @Test +- public void testAbortNotCommitted() throws Exception { +- addPrincipals(); +- +- assertTrue(module.login()); +- assertTrue(module.abort()); +- +- verifyStateReset(); +- } +- +- @Test +- public void testAbortCommitted() throws Exception { +- addPrincipals(); +- +- assertTrue(module.login()); +- assertTrue(module.commit()); +- assertTrue(module.abort()); +- +- verifyStateReset(); +- } +- +- @Test +- public void testLogout() throws Exception { +- addPrincipals(); +- +- assertTrue(module.login()); +- assertTrue(module.commit()); +- assertTrue(module.logout()); +- +- verifyStateReset(); +- } +- +- @SuppressWarnings("restriction") +- private void addPrincipals() { +- subject.getPrincipals().add(new com.sun.security.auth.UnixPrincipal("TEST")); +- subject.getPrincipals().add(new com.sun.security.auth.UnixNumericUserPrincipal(9000)); +- subject.getPrincipals().add(new com.sun.security.auth.UnixNumericGroupPrincipal(9001, true)); +- } +- +- private void verifyFailedLogin() { +- try { +- module.login(); +- fail("Expected LoginException"); +- } catch (LoginException e) { +- assertFalse(module.isLoggedIn()); +- assertNull(module.getPrincipal()); +- assertFalse(module.isCommitted()); +- assertTrue(subject.getPrincipals(AgentProxyPrincipal.class).isEmpty()); +- } +- } +- +- @SuppressWarnings("restriction") +- private void verifyStateReset() { +- assertFalse(module.isLoggedIn()); +- assertFalse(module.isCommitted()); +- assertNull(module.getPrincipal()); +- assertTrue(subject.getPrincipals(AgentProxyPrincipal.class).isEmpty()); +- assertFalse(subject.getPrincipals(com.sun.security.auth.UnixPrincipal.class).isEmpty()); +- assertFalse(subject.getPrincipals(com.sun.security.auth.UnixNumericUserPrincipal.class).isEmpty()); +- assertFalse(subject.getPrincipals(com.sun.security.auth.UnixNumericGroupPrincipal.class).isEmpty()); +- } +- +-} +diff -urN thermostat-1.0.4.old/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyTest.java thermostat-1.0.4/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyTest.java +--- thermostat-1.0.4.old/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyTest.java 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyTest.java 2014-12-05 14:26:44.831484048 -0500 +@@ -36,106 +36,99 @@ + + package com.redhat.thermostat.agent.proxy.server; + +-import static org.junit.Assert.assertEquals; +-import static org.junit.Assert.assertFalse; +-import static org.junit.Assert.assertTrue; +-import static org.mockito.Matchers.any; + import static org.mockito.Mockito.doThrow; + 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.rmi.RemoteException; +-import java.rmi.registry.Registry; +-import java.util.Timer; +-import java.util.TimerTask; ++import java.io.IOException; ++import java.io.PrintStream; + ++import org.junit.After; + import org.junit.Before; + import org.junit.Test; +-import org.mockito.ArgumentCaptor; + +-import com.redhat.thermostat.agent.proxy.common.AgentProxyListener; +-import com.redhat.thermostat.agent.proxy.common.AgentProxyLogin; ++import com.redhat.thermostat.agent.proxy.server.AgentProxy.ControlCreator; + + public class AgentProxyTest { + +- private AgentProxyNativeUtils nativeUtils; +- private RegistryUtils registryUtils; +- private Registry registry; +- private AgentProxyLogin loginStub; +- private AgentProxyListener listener; +- private Timer timeoutTimer; ++ private static final String JMX_URL = "service:jmx:rmi://myHost:1099/blah"; ++ ++ private AgentProxyControlImpl control; ++ private PrintStream outStream; + + @Before + public void setup() throws Exception { +- registry = mock(Registry.class); +- listener = mock(AgentProxyListener.class); +- when(registry.lookup(AgentProxyListener.REMOTE_PREFIX + "0")).thenReturn(listener); +- registryUtils = mock(RegistryUtils.class); +- when(registryUtils.getRegistry()).thenReturn(registry); +- loginStub = mock(AgentProxyLogin.class); +- when(registryUtils.exportObject(any(AgentProxyLogin.class))).thenReturn(loginStub); +- +- nativeUtils = mock(AgentProxyNativeUtils.class); +- ProcessUserInfoBuilder builder = mock(ProcessUserInfoBuilder.class); +- when(builder.build(0)).thenReturn(new UnixCredentials(9000, 9001, 0)); +- timeoutTimer = mock(Timer.class); +- AgentProxy.setRegistryUtils(registryUtils); +- AgentProxy.setNativeUtils(nativeUtils); +- AgentProxy.setProcessUserInfoBuilder(builder); +- AgentProxy.setTimeoutTimer(timeoutTimer); ++ ControlCreator creator = mock(ControlCreator.class); ++ control = mock(AgentProxyControlImpl.class); ++ when(control.getConnectorAddress()).thenReturn(JMX_URL); ++ outStream = mock(PrintStream.class); ++ when(creator.create(0)).thenReturn(control); ++ AgentProxy.setControlCreator(creator); ++ AgentProxy.setOutStream(outStream); ++ } ++ ++ @After ++ public void teardown() throws Exception { ++ AgentProxy.setControlCreator(new ControlCreator()); ++ AgentProxy.setOutStream(System.out); + } + + @Test + public void testMainSuccess() throws Exception { +- assertFalse(AgentProxy.isBound()); +- + // Invoke main with PID of 0 + AgentProxy.main(new String[] { "0" }); + +- assertTrue(AgentProxy.isBound()); +- +- // Verify timeout set +- verify(timeoutTimer).schedule(any(TimerTask.class), any(Long.class)); +- +- // Verify native library loaded and credentials properly set +- verify(nativeUtils).loadLibrary(); +- verify(nativeUtils).setCredentials(9000, 9001); ++ verify(control).attach(); ++ verify(control).getConnectorAddress(); ++ verify(control).detach(); ++ verify(outStream).println(JMX_URL); ++ } ++ ++ @Test ++ public void testMainAttachFails() throws Exception { ++ // Simulate failure binding the login object ++ doThrow(new IOException()).when(control).attach(); + +- // Verify login object exported +- AgentProxyLogin proxyLogin = AgentProxy.getAgentProxyLogin(); +- verify(registryUtils).exportObject(proxyLogin); +- verify(registry).rebind(AgentProxyLogin.REMOTE_PREFIX + "0", loginStub); ++ // Invoke main with PID of 0 ++ AgentProxy.main(new String[] { "0" }); + +- // Verify listener notified with positive response +- verify(listener).serverStarted(); ++ verify(control).attach(); ++ verify(control, never()).getConnectorAddress(); ++ verify(control, never()).detach(); ++ verify(outStream, never()).println(JMX_URL); ++ } ++ ++ @Test ++ public void testMainGetAddressFails() throws Exception { ++ // Simulate failure binding the login object ++ doThrow(new IOException()).when(control).getConnectorAddress(); + +- // Shutdown server +- ShutdownListener shutdownListener = AgentProxy.getShutdownListener(); +- shutdownListener.shutdown(); ++ // Invoke main with PID of 0 ++ AgentProxy.main(new String[] { "0" }); + +- // Verify login object unexported +- verify(registry).unbind(AgentProxyLogin.REMOTE_PREFIX + "0"); +- verify(registryUtils).unexportObject(proxyLogin); ++ verify(control).attach(); ++ verify(control).getConnectorAddress(); + +- assertFalse(AgentProxy.isBound()); ++ // Should detach, but not print URL ++ verify(control).detach(); ++ verify(outStream, never()).println(JMX_URL); + } + + @Test +- public void testMainFailure() throws Exception { ++ public void testMainDetachFails() throws Exception { + // Simulate failure binding the login object +- RemoteException ex = new RemoteException("TEST"); +- doThrow(ex).when(registry).rebind(AgentProxyLogin.REMOTE_PREFIX + "0", loginStub); ++ doThrow(new IOException()).when(control).detach(); + + // Invoke main with PID of 0 + AgentProxy.main(new String[] { "0" }); + +- // Verify listener notified with negative response +- ArgumentCaptor errorCaptor = ArgumentCaptor.forClass(Exception.class); +- verify(listener).serverFailedToStart(errorCaptor.capture()); +- assertEquals(ex, errorCaptor.getValue().getCause()); +- +- assertFalse(AgentProxy.isBound()); ++ // All should be called ++ verify(control).attach(); ++ verify(control).getConnectorAddress(); ++ verify(control).detach(); ++ verify(outStream).println(JMX_URL); + } + + } +diff -urN thermostat-1.0.4.old/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/ProcessUserInfoBuilderTest.java thermostat-1.0.4/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/ProcessUserInfoBuilderTest.java +--- thermostat-1.0.4.old/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/ProcessUserInfoBuilderTest.java 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/ProcessUserInfoBuilderTest.java 1969-12-31 19:00:00.000000000 -0500 +@@ -1,84 +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 +- * . +- * +- * 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.proxy.server; +- +-import static org.junit.Assert.assertEquals; +-import static org.mockito.Matchers.anyInt; +-import static org.mockito.Mockito.mock; +-import static org.mockito.Mockito.when; +- +-import java.io.IOException; +-import java.io.StringReader; +- +-import org.junit.Test; +- +-import com.redhat.thermostat.common.tools.ApplicationException; +- +-public class ProcessUserInfoBuilderTest { +- +- @Test +- public void testBuild() throws IOException { +- StringReader reader = new StringReader("Uid: 2000 2000 2000 2000\nGid: 2001 2001 2001 2001"); +- ProcDataSource source = mock(ProcDataSource.class); +- when(source.getStatusReader(anyInt())).thenReturn(reader); +- ProcessUserInfoBuilder builder = new ProcessUserInfoBuilder(source); +- UnixCredentials creds = builder.build(1); +- +- assertEquals(2000, creds.getUid()); +- assertEquals(2001, creds.getGid()); +- assertEquals(1, creds.getPid()); +- } +- +- @Test(expected=IOException.class) +- public void testBuildErrorUid() throws IOException, ApplicationException { +- StringReader reader = new StringReader("Gid: 2001 2001 2001 2001"); +- ProcDataSource source = mock(ProcDataSource.class); +- when(source.getStatusReader(anyInt())).thenReturn(reader); +- ProcessUserInfoBuilder builder = new ProcessUserInfoBuilder(source); +- builder.build(0); +- } +- +- @Test(expected=IOException.class) +- public void testBuildErrorGid() throws IOException, ApplicationException { +- StringReader reader = new StringReader("Uid: 2000 2000 2000 2000"); +- ProcDataSource source = mock(ProcDataSource.class); +- when(source.getStatusReader(anyInt())).thenReturn(reader); +- ProcessUserInfoBuilder builder = new ProcessUserInfoBuilder(source); +- builder.build(0); +- } +- +-} +diff -urN thermostat-1.0.4.old/distribution/assembly/core-assembly.xml thermostat-1.0.4/distribution/assembly/core-assembly.xml +--- thermostat-1.0.4.old/distribution/assembly/core-assembly.xml 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/distribution/assembly/core-assembly.xml 2014-12-05 14:26:44.832484054 -0500 +@@ -59,7 +59,6 @@ + com.redhat.thermostat:thermostat-agent-core + com.redhat.thermostat:thermostat-agent-cli + com.redhat.thermostat:thermostat-agent-command +- com.redhat.thermostat:thermostat-agent-proxy-common + com.redhat.thermostat:thermostat-agent-proxy-server + com.redhat.thermostat:thermostat-killvm-agent + com.redhat.thermostat:thermostat-killvm-client-swing +diff -urN thermostat-1.0.4.old/distribution/config/agent_proxy_jaas.conf thermostat-1.0.4/distribution/config/agent_proxy_jaas.conf +--- thermostat-1.0.4.old/distribution/config/agent_proxy_jaas.conf 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/distribution/config/agent_proxy_jaas.conf 1969-12-31 19:00:00.000000000 -0500 +@@ -1,7 +0,0 @@ +-UnixLogin { +- com.sun.security.auth.module.UnixLoginModule required debug=false; +-}; +- +-AgentProxyLogin { +- com.redhat.thermostat.agent.proxy.server.AgentProxyLoginModule required debug=false; +-}; +diff -urN thermostat-1.0.4.old/distribution/config/commands/agent.properties thermostat-1.0.4/distribution/config/commands/agent.properties +--- thermostat-1.0.4.old/distribution/config/commands/agent.properties 2014-12-05 14:25:26.298012971 -0500 ++++ thermostat-1.0.4/distribution/config/commands/agent.properties 2014-12-05 14:26:44.833484060 -0500 +@@ -8,7 +8,6 @@ + com.redhat.thermostat.process=${project.version}, \ + com.redhat.thermostat.common.core=${project.version}, \ + com.redhat.thermostat.agent.cli=${project.version}, \ +- com.redhat.thermostat.agent.proxy.common=${project.version}, \ + com.redhat.thermostat.common.command=${project.version}, \ + com.redhat.thermostat.agent.command=${project.version}, \ + com.redhat.thermostat.killvm.agent=${project.version}, \ +diff -urN thermostat-1.0.4.old/distribution/config/commands/service.properties thermostat-1.0.4/distribution/config/commands/service.properties +--- thermostat-1.0.4.old/distribution/config/commands/service.properties 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/distribution/config/commands/service.properties 2014-12-05 14:26:44.833484060 -0500 +@@ -10,7 +10,6 @@ + com.redhat.thermostat.agent.command=${project.version}, \ + com.redhat.thermostat.storage.cli=${project.version}, \ + com.redhat.thermostat.agent.cli=${project.version}, \ +- com.redhat.thermostat.agent.proxy.common=${project.version}, \ + org.jboss.netty=${netty.version} + + description = starts and stops the thermostat storage and agent +diff -urN thermostat-1.0.4.old/distribution/pom.xml thermostat-1.0.4/distribution/pom.xml +--- thermostat-1.0.4.old/distribution/pom.xml 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/distribution/pom.xml 2014-12-05 14:26:44.834484066 -0500 +@@ -145,7 +145,6 @@ + thermostat-users.properties + thermostat-roles.properties + thermostat_jaas.conf +- agent_proxy_jaas.conf + db.properties + logging.properties + osgi-export.properties +@@ -209,8 +208,6 @@ + todir="${project.build.directory}/image/libs/native" /> + +- + + +diff -urN thermostat-1.0.4.old/distribution/scripts/thermostat thermostat-1.0.4/distribution/scripts/thermostat +--- thermostat-1.0.4.old/distribution/scripts/thermostat 2014-12-05 14:25:46.545134421 -0500 ++++ thermostat-1.0.4/distribution/scripts/thermostat 2014-12-05 14:26:44.834484066 -0500 +@@ -60,8 +60,6 @@ + SERVICE_CLASSPATH="${SERVICE_CLASSPATH}:${THERMOSTAT_LIBS}/thermostat-launcher-@project.version@.jar" + SERVICE_CLASSPATH="${SERVICE_CLASSPATH}:${THERMOSTAT_LIBS}/thermostat-main-@project.version@.jar" + SERVICE_CLASSPATH="${SERVICE_CLASSPATH}:${THERMOSTAT_LIBS}/thermostat-shared-config-@project.version@.jar" +-# This needs to be on the classpath for the RMI registry to find it +-SERVICE_CLASSPATH="${SERVICE_CLASSPATH}:${THERMOSTAT_LIBS}/thermostat-agent-proxy-common-@project.version@.jar" + SERVICE_CLASSPATH="${TOOLS_JAR}:${SERVICE_CLASSPATH}" + + THERMOSTAT_MAIN="com.redhat.thermostat.main.Thermostat" +diff -urN thermostat-1.0.4.old/distribution/scripts/thermostat-agent-proxy thermostat-1.0.4/distribution/scripts/thermostat-agent-proxy +--- thermostat-1.0.4.old/distribution/scripts/thermostat-agent-proxy 2014-06-02 14:46:53.000000000 -0400 ++++ thermostat-1.0.4/distribution/scripts/thermostat-agent-proxy 2014-12-05 14:26:44.835484072 -0500 +@@ -40,6 +40,10 @@ + JAVA_DIR="@java.dir@" + JAVA="@java.home@/bin/java" + ++if [ "$#" -lt 2 ]; then ++ echo "usage: $0 " >&2 ++fi ++ + if [ x"$THERMOSTAT_INSTALL_DIR" = x ] ; then + THERMOSTAT_INSTALL_DIR="@thermostat.home@" + fi +@@ -56,19 +60,20 @@ + # JARs necessary for the server + SERVICE_CLASSPATH="${THERMOSTAT_LIBS}/thermostat-common-core-@project.version@.jar" + SERVICE_CLASSPATH="${SERVICE_CLASSPATH}:${THERMOSTAT_LIBS}/thermostat-shared-config-@project.version@.jar" +-SERVICE_CLASSPATH="${SERVICE_CLASSPATH}:${THERMOSTAT_LIBS}/thermostat-agent-proxy-common-@project.version@.jar" + SERVICE_CLASSPATH="${SERVICE_CLASSPATH}:${THERMOSTAT_LIBS}/thermostat-agent-proxy-server-@project.version@.jar" + SERVICE_CLASSPATH="${TOOLS_JAR}:${SERVICE_CLASSPATH}" + + AGENT_PROXY_CLASS="com.redhat.thermostat.agent.proxy.server.AgentProxy" + +-JAAS_CONFIG="${THERMOSTAT_HOME}/etc/agent_proxy_jaas.conf" +- + # Set this to remote debug + if [ x"$THERMOSTAT_DEBUG" != x ] ; then + DEBUG_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=1082" + fi + + # Start server +-${JAVA} -cp ${SERVICE_CLASSPATH} ${DEBUG_OPTS} "-Djava.security.auth.login.config=${JAAS_CONFIG}" \ +-"-Djava.rmi.server.randomIDs=true" ${AGENT_PROXY_CLASS} "$1" ++# Drop permissions, if root ++if [ "$(/bin/id -u)" -eq 0 ]; then ++ /bin/su "$2" -c "${JAVA} -cp ${SERVICE_CLASSPATH} ${DEBUG_OPTS} ${AGENT_PROXY_CLASS} $1" ++else ++ ${JAVA} -cp ${SERVICE_CLASSPATH} ${DEBUG_OPTS} ${AGENT_PROXY_CLASS} $1 ++fi diff --git a/SPECS/thermostat.spec b/SPECS/thermostat.spec index 0020698..6113c3e 100644 --- a/SPECS/thermostat.spec +++ b/SPECS/thermostat.spec @@ -85,7 +85,7 @@ Version: %{major}.%{minor}.%{patchlevel} # 60.X where X is an increasing int. 60 for rhel-6. We use # 70.X for rhel-7. For some reason we cannot rely on the # dist tag. -Release: 70.3%{?dist} +Release: 70.6%{?dist} Summary: A monitoring and serviceability tool for OpenJDK License: GPLv2+ with exceptions and OFL URL: http://icedtea.classpath.org/thermostat/ @@ -124,6 +124,9 @@ Patch2: fix_loglevel.patch # thermostat we rely on RPM enforcing a working set of bundle<=>version pairs that # work. See: http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=1591 Patch3: ignore_bundle_versions.patch +# This security fix is scheduled to be upstreamed in the next maintenance release +# of the 1.0 branch. +Patch4: agent_remove_rmi.patch BuildRequires: maven-local BuildRequires: xmvn @@ -178,6 +181,9 @@ Requires: mongodb24 Requires: mongodb24-mongodb Requires: mongodb24-mongodb-server +# This module has been removed to fix RHBZ#1170141 +Obsoletes: %{scl_prefix}mvn(com.redhat.thermostat:thermostat-agent-proxy-common) <= %{version} + Requires(post): systemd Requires(preun): systemd Requires(postun): systemd @@ -228,6 +234,7 @@ for Thermostat's Web layer. %patch1 -p1 %patch2 -p1 %patch3 -p1 +%patch4 -p1 # Fix up artifact names which have different name upstream # lucene @@ -252,7 +259,6 @@ for Thermostat's Web layer. %pom_remove_plugin org.codehaus.mojo:exec-maven-plugin agent/core %pom_remove_plugin org.codehaus.mojo:exec-maven-plugin keyring %pom_remove_plugin org.codehaus.mojo:exec-maven-plugin laf-utils -%pom_remove_plugin org.codehaus.mojo:exec-maven-plugin agent/proxy/server # Remove jacoco-coverage plugin (in main pom.xml and web/war/pom.xml) %pom_remove_plugin org.jacoco:jacoco-maven-plugin @@ -281,9 +287,7 @@ for Thermostat's Web layer. %pom_xpath_remove "pom:dependencies/pom:dependency[pom:groupId='com.sun']/pom:scope" vm-heap-analysis/client-swing %pom_xpath_remove "pom:dependencies/pom:dependency[pom:groupId='com.sun']/pom:scope" vm-heap-analysis/client-core %pom_xpath_remove "pom:dependencies/pom:dependency[pom:groupId='com.sun']/pom:systemPath" agent/core -%pom_xpath_remove "pom:dependencies/pom:dependency[pom:groupId='com.sun']/pom:scope" agent/proxy/common %pom_xpath_remove "pom:dependencies/pom:dependency[pom:groupId='com.sun']/pom:scope" agent/proxy/server -%pom_xpath_remove "pom:dependencies/pom:dependency[pom:groupId='com.sun']/pom:systemPath" agent/proxy/common %pom_xpath_remove "pom:dependencies/pom:dependency[pom:groupId='com.sun']/pom:systemPath" agent/proxy/server %pom_xpath_remove "pom:dependencies/pom:dependency[pom:groupId='com.sun']/pom:systemPath" common/core %pom_xpath_remove "pom:dependencies/pom:dependency[pom:groupId='com.sun']/pom:systemPath" thread/collector @@ -353,13 +357,6 @@ pushd agent/core src/main/java/com/redhat/thermostat/utils/username/internal/UserNameUtilImpl.java make all popd -pushd agent/proxy/server - mkdir -p target/classes - javac -cp ../../../config/target/classes \ - -d target/classes \ - src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyNativeUtils.java - make all -popd pushd laf-utils mkdir -p target/classes javac -cp ../config/target/classes \ @@ -468,14 +465,12 @@ pushd distribution/target/image/libs # %{_libdir}/%{pkg_name} next. for i in thermostat-keyring-*.jar \ thermostat-agent-core-*.jar \ - thermostat-agent-proxy-server-*.jar \ thermostat-laf-utils-*.jar; do ln -s %{_libdir}/%{pkg_name}/$i %{buildroot}%{_jnidir}/$i done # JNI files are in %{_libdir} mv thermostat-keyring-*.jar \ thermostat-agent-core-*.jar \ - thermostat-agent-proxy-server-*.jar \ thermostat-laf-utils-*.jar \ %{buildroot}%{_libdir}/%{pkg_name} # Make native libs executable so that debuginfos get properly @@ -757,7 +752,6 @@ fi %config(noreplace) %{_sysconfdir}/%{pkg_name}/logging.properties %config(noreplace) %{_sysconfdir}/%{pkg_name}/osgi-export.properties %config(noreplace) %{_sysconfdir}/%{pkg_name}/ssl.properties -%config(noreplace) %{_sysconfdir}/%{pkg_name}/agent_proxy_jaas.conf # Required for systemd services %config(noreplace) %{_sysconfdir}/sysconfig/%{pkg_name} # thermostat.desktop lives in /usr/share/applications @@ -779,11 +773,7 @@ fi %attr(0770,thermostat,thermostat) %dir %{system_cachedir} %attr(0770,thermostat,thermostat) %dir %{system_logdir} %attr(0770,thermostat,thermostat) %dir %{system_statedir} -# Agent-proxy installs into jni_dir, but we symlink to it in -# java_dir. Own the symlink here. -%{_javadir}/%{pkg_name}/thermostat-agent-proxy-server.jar # Own directories we ship libs in. See RHBZ#1057169 -%dir %{_jnidir}/%{pkg_name} %dir %{_javadir}/%{pkg_name} %files javadoc @@ -805,6 +795,18 @@ fi %attr(0770,tomcat,tomcat) %dir %{_root_localstatedir}/log/%{thermostat_tomcat_service_name} %changelog +* Mon Dec 08 2014 Elliott Baron - 1.0.4-70.6 +- Add Obsoletes for agent-proxy-common module. +- Resolves: RHBZ#1170141 + +* Fri Dec 05 2014 Elliott Baron - 1.0.4-70.5 +- Clean up remnants of agent-proxy-common module. +- Resolves: RHBZ#1170141 + +* Tue Dec 02 2014 Elliott Baron - 1.0.4-70.4 +- Remove RMI from agent. +- Resolves: RHBZ#1170141 + * Tue Jul 15 2014 Severin Gehwolf - 1.0.4-70.3 - Fix dangling symlinks for jline2, google-gson and apache-commons-fileupload dependencies.