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.