changeset 1529:33ad3d556e28

Garbage Collection command addition. Reviewed-by: jerboaa, neugens, omajid Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2014-October/011328.html
author Jie Kang <jkang@redhat.com>
date Mon, 27 Oct 2014 14:29:52 -0400
parents b6839c766124
children ccbfa9774745
files vm-gc/command/pom.xml vm-gc/command/src/main/java/com/redhat/thermostat/vm/gc/command/internal/Activator.java vm-gc/command/src/main/java/com/redhat/thermostat/vm/gc/command/internal/GCCommand.java vm-gc/command/src/main/java/com/redhat/thermostat/vm/gc/command/internal/GCCommandListener.java vm-gc/command/src/main/java/com/redhat/thermostat/vm/gc/command/locale/LocaleResources.java vm-gc/command/src/main/resources/com/redhat/thermostat/gc/command/locale/strings.properties vm-gc/command/src/test/java/com/redhat/thermostat/vm/gc/command/internal/ActivatorTest.java vm-gc/command/src/test/java/com/redhat/thermostat/vm/gc/command/internal/GCCommandListenerTest.java vm-gc/command/src/test/java/com/redhat/thermostat/vm/gc/command/internal/GCCommandTest.java vm-gc/command/src/test/java/com/redhat/thermostat/vm/gc/command/locale/LocaleResourcesTest.java vm-gc/distribution/pom.xml vm-gc/distribution/thermostat-plugin.xml vm-gc/pom.xml vm-gc/remote-collector-client-common/src/main/java/com/redhat/thermostat/gc/remote/client/common/RequestGCAction.java vm-gc/remote-collector-client-common/src/main/java/com/redhat/thermostat/gc/remote/common/GCRequest.java vm-gc/remote-collector-client-common/src/test/java/com/redhat/thermostat/gc/remote/common/GCRequestTest.java vm-gc/remote-collector-command/pom.xml vm-gc/remote-collector-command/src/main/java/com/redhat/thermostat/gc/remote/command/GCCommandReceiver.java vm-gc/remote-collector-command/src/main/java/com/redhat/thermostat/gc/remote/command/GCRequestReceiver.java vm-gc/remote-collector-command/src/main/java/com/redhat/thermostat/gc/remote/command/osgi/Activator.java vm-gc/remote-collector-command/src/main/java/com/redhat/thermostat/gc/remote/command/osgi/GCCommandReceiverActivator.java vm-gc/remote-collector-command/src/test/java/com/redhat/thermostat/gc/remote/command/osgi/ActivatorTest.java vm-gc/remote-collector-common/src/main/java/com/redhat/thermostat/gc/remote/common/command/GCAction.java vm-gc/remote-collector-common/src/main/java/com/redhat/thermostat/gc/remote/common/command/GCCommand.java vm-memory/client-core/src/main/java/com/redhat/thermostat/vm/memory/client/core/MemoryStatsView.java vm-memory/client-core/src/main/java/com/redhat/thermostat/vm/memory/client/core/internal/MemoryStatsController.java vm-memory/client-core/src/test/java/com/redhat/thermostat/vm/memory/client/core/internal/MemoryStatsControllerTest.java vm-memory/client-swing/src/main/java/com/redhat/thermostat/vm/memory/client/swing/internal/MemoryStatsViewImpl.java
diffstat 28 files changed, 1353 insertions(+), 233 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-gc/command/pom.xml	Mon Oct 27 14:29:52 2014 -0400
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright 2012-2014 Red Hat, Inc.
+
+ This file is part of Thermostat.
+
+ Thermostat is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ Thermostat is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Thermostat; see the file COPYING.  If not see
+ <http://www.gnu.org/licenses/>.
+
+ Linking this code with other modules is making a combined work
+ based on this code.  Thus, the terms and conditions of the GNU
+ General Public License cover the whole combination.
+
+ As a special exception, the copyright holders of this code give
+ you permission to link this code with independent modules to
+ produce an executable, regardless of the license terms of these
+ independent modules, and to copy and distribute the resulting
+ executable under terms of your choice, provided that you also
+ meet, for each linked independent module, the terms and conditions
+ of the license of that module.  An independent module is a module
+ which is not derived from or based on this code.  If you modify
+ this code, you may extend this exception to your version of the
+ library, but you are not obligated to do so.  If you do not wish
+ to do so, delete this exception statement from your version.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>com.redhat.thermostat</groupId>
+    <artifactId>thermostat-vm-gc</artifactId>
+    <version>1.1.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>thermostat-vm-gc-command</artifactId>
+  <packaging>bundle</packaging>
+
+  <name>Thermostat GC Plugin Command</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-common-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.core</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.compendium</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-common-test</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-shared-config</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-client-cli</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-gc-remote-collector-client-common</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-client-command</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-storage-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
+            <Bundle-SymbolicName>com.redhat.thermostat.vm.gc.command</Bundle-SymbolicName>
+            <Bundle-Activator>com.redhat.thermostat.vm.gc.command.internal.Activator</Bundle-Activator>
+            <Export-Package>
+              com.redhat.thermostat.vm.gc.command
+            </Export-Package>
+            <Private-Package>
+              com.redhat.thermostat.vm.gc.command.internal,
+              com.redhat.thermostat.vm.gc.command.locale,
+            </Private-Package>
+            <!-- Do not autogenerate uses clauses in Manifests -->
+            <_nouses>true</_nouses>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-gc/command/src/main/java/com/redhat/thermostat/vm/gc/command/internal/Activator.java	Mon Oct 27 14:29:52 2014 -0400
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2012-2014 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.vm.gc.command.internal;
+
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+import com.redhat.thermostat.client.command.RequestQueue;
+import com.redhat.thermostat.common.MultipleServiceTracker;
+import com.redhat.thermostat.common.cli.Command;
+import com.redhat.thermostat.gc.remote.common.GCRequest;
+import com.redhat.thermostat.storage.dao.AgentInfoDAO;
+import com.redhat.thermostat.storage.dao.HostInfoDAO;
+import com.redhat.thermostat.storage.dao.VmInfoDAO;
+
+public class Activator implements BundleActivator {
+
+    private MultipleServiceTracker serviceTracker;
+    private ServiceRegistration registration;
+
+    private final GCCommand command = new GCCommand(new GCCommandListener());
+
+    @Override
+    public void start(BundleContext context) throws Exception {
+        Class<?>[] serviceDeps = new Class<?>[] {
+                HostInfoDAO.class,
+                AgentInfoDAO.class,
+                VmInfoDAO.class,
+                GCRequest.class,
+                RequestQueue.class,
+        };
+
+        serviceTracker = new MultipleServiceTracker(context, serviceDeps, new MultipleServiceTracker.Action() {
+            @Override
+            public void dependenciesAvailable(Map<String, Object> services) {
+                HostInfoDAO hostDAO = (HostInfoDAO) services.get(HostInfoDAO.class.getName());
+                AgentInfoDAO agentDao = (AgentInfoDAO) services.get(AgentInfoDAO.class.getName());
+                VmInfoDAO vmInfoDAO = (VmInfoDAO) services.get(VmInfoDAO.class.getName());
+                GCRequest request = (GCRequest) services.get(GCRequest.class.getName());
+
+                command.setServices(request, agentDao, hostDAO, vmInfoDAO);
+            }
+
+            @Override
+            public void dependenciesUnavailable() {
+                command.setServices(null, null, null, null);
+            }
+        });
+
+        serviceTracker.open();
+
+        Hashtable<String,String> properties = new Hashtable<>();
+        properties.put(Command.NAME, "gc");
+        registration = context.registerService(Command.class.getName(), command, properties);
+    }
+
+    @Override
+    public void stop(BundleContext context) throws Exception {
+        serviceTracker.close();
+        registration.unregister();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-gc/command/src/main/java/com/redhat/thermostat/vm/gc/command/internal/GCCommand.java	Mon Oct 27 14:29:52 2014 -0400
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2012-2014 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.vm.gc.command.internal;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+import com.redhat.thermostat.client.cli.HostVMArguments;
+import com.redhat.thermostat.common.cli.AbstractCommand;
+import com.redhat.thermostat.common.cli.CommandContext;
+import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.gc.remote.common.GCRequest;
+import com.redhat.thermostat.shared.locale.Translate;
+import com.redhat.thermostat.storage.core.HostRef;
+import com.redhat.thermostat.storage.core.VmId;
+import com.redhat.thermostat.storage.core.VmRef;
+import com.redhat.thermostat.storage.dao.AgentInfoDAO;
+import com.redhat.thermostat.storage.dao.HostInfoDAO;
+import com.redhat.thermostat.storage.dao.VmInfoDAO;
+import com.redhat.thermostat.storage.model.VmInfo;
+import com.redhat.thermostat.vm.gc.command.locale.LocaleResources;
+
+public class GCCommand extends AbstractCommand {
+
+    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
+
+    private GCRequest request;
+    private AgentInfoDAO agentInfoDAO;
+    private VmInfoDAO vmInfoDAO;
+    private HostInfoDAO hostInfoDAO;
+    private final GCCommandListener listener;
+    private Semaphore servicesAvailable = new Semaphore(0);
+
+    public GCCommand(GCCommandListener listener) {
+        this.listener = listener;
+    }
+
+    @Override
+    public void run(CommandContext ctx) throws CommandException {
+        waitForServices(500l);
+
+        requireNonNull(hostInfoDAO, translator.localize(LocaleResources.HOST_SERVICE_UNAVAILABLE));
+        requireNonNull(vmInfoDAO, translator.localize(LocaleResources.VM_SERVICE_UNAVAILABLE));
+        requireNonNull(agentInfoDAO, translator.localize(LocaleResources.AGENT_SERVICE_UNAVAILABLE));
+        requireNonNull(request, translator.localize(LocaleResources.GCREQUEST_SERVICE_UNAVAILABLE));
+
+        listener.setOut(ctx.getConsole().getOutput());
+        listener.setErr(ctx.getConsole().getError());
+
+        HostVMArguments args = new HostVMArguments(ctx.getArguments(), false, true);
+
+        VmId vmId = new VmId(args.getVM().getVmId());
+        attemptGC(vmId);
+    }
+
+    private void waitForServices(long timeout) {
+        try {
+            servicesAvailable.tryAcquire(timeout, TimeUnit.MILLISECONDS);
+        } catch (InterruptedException e) {
+            translator.localize(LocaleResources.COMMAND_INTERRUPTED);
+        }
+    }
+
+    private void attemptGC(VmId vmId) throws CommandException {
+        VmInfo result = vmInfoDAO.getVmInfo(vmId);
+
+        if (result == null) {
+            throw new CommandException(translator.localize(LocaleResources.VM_NOT_FOUND, vmId.get()));
+        } else {
+            HostRef dummyRef = new HostRef(result.getAgentId(), "dummy");
+            sendGCRequest(new VmRef(dummyRef, result.getVmId(), result.getVmPid(), result.getVmName()));
+        }
+    }
+
+    private void sendGCRequest(VmRef vmRef) throws CommandException {
+        request.sendGCRequestToAgent(vmRef, agentInfoDAO, listener);
+
+        waitForListenerResponse();
+    }
+
+    private void waitForListenerResponse() {
+        try {
+            listener.await(1000l);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public void setServices(GCRequest request, AgentInfoDAO agentInfoDAO, HostInfoDAO hostInfoDAO, VmInfoDAO vmInfoDAO) {
+        this.request = request;
+        this.agentInfoDAO = agentInfoDAO;
+        this.hostInfoDAO = hostInfoDAO;
+        this.vmInfoDAO = vmInfoDAO;
+
+        if (request == null || agentInfoDAO == null || hostInfoDAO == null || vmInfoDAO == null) {
+            servicesUnavailable();
+        } else {
+            servicesAvailable();
+        }
+    }
+
+    private void servicesAvailable() {
+        this.servicesAvailable.release();
+    }
+
+    private void servicesUnavailable() {
+        this.servicesAvailable.drainPermits();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-gc/command/src/main/java/com/redhat/thermostat/vm/gc/command/internal/GCCommandListener.java	Mon Oct 27 14:29:52 2014 -0400
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2012-2014 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.vm.gc.command.internal;
+
+import java.io.PrintStream;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.redhat.thermostat.common.command.Request;
+import com.redhat.thermostat.common.command.RequestResponseListener;
+import com.redhat.thermostat.common.command.Response;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+import com.redhat.thermostat.shared.locale.Translate;
+import com.redhat.thermostat.vm.gc.command.locale.LocaleResources;
+
+public class GCCommandListener implements RequestResponseListener {
+    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
+    private static final Logger logger = LoggingUtils
+            .getLogger(GCCommandListener.class);
+
+    private final CountDownLatch latch = new CountDownLatch(1);
+
+    private PrintStream out;
+    private PrintStream err;
+
+    @Override
+    public void fireComplete(Request request, Response response) {
+        String message;
+        String pid;
+
+        switch (response.getType()) {
+            case ERROR:
+                pid = request.getParameter("VM_PID");
+                message = "GC Request error for VM PID " + pid;
+                logger.log(Level.SEVERE, message);
+                if (err != null) {
+                    err.println(translator.localize(LocaleResources.GC_ERROR_RESULT, pid).getContents());
+                }
+                break;
+            case OK:
+                pid = request.getParameter("VM_PID");
+                message = "Garbage Collection performed on VM with PID " + pid;
+                logger.log(Level.INFO, message);
+                if (out != null) {
+                    out.println(translator.localize(LocaleResources.GC_SUCCESS_RESULT, pid).getContents());
+                }
+                break;
+            default:
+                message = "Unknown result from GC command";
+                logger.log(Level.WARNING, message);
+                if (out != null) {
+                    out.println(translator.localize(LocaleResources.GC_UNKNOWN_RESULT).getContents());
+                }
+                break;
+        }
+        latch.countDown();
+    }
+
+    public synchronized void await(long timeout) throws InterruptedException {
+        this.latch.await(timeout, TimeUnit.MILLISECONDS);
+    }
+
+    public void setOut(PrintStream out) {
+        this.out = out;
+    }
+
+    public void setErr(PrintStream err) {
+        this.err = err;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-gc/command/src/main/java/com/redhat/thermostat/vm/gc/command/locale/LocaleResources.java	Mon Oct 27 14:29:52 2014 -0400
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2012-2014 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.vm.gc.command.locale;
+
+import com.redhat.thermostat.shared.locale.Translate;
+
+public enum LocaleResources {
+
+    GCREQUEST_SERVICE_UNAVAILABLE,
+    GC_FAILED,
+    AGENT_SERVICE_UNAVAILABLE,
+    HOST_SERVICE_UNAVAILABLE,
+    VM_SERVICE_UNAVAILABLE,
+    LISTENER_UNAVAILABLE,
+    VM_NOT_FOUND, COMMAND_INTERRUPTED, GC_ERROR_RESULT, GC_SUCCESS_RESULT, GC_UNKNOWN_RESULT;
+
+    static final String RESOURCE_BUNDLE =
+            "com.redhat.thermostat.gc.command.locale.strings";
+
+    public static Translate<LocaleResources> createLocalizer() {
+        return new Translate(RESOURCE_BUNDLE, LocaleResources.class);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-gc/command/src/main/resources/com/redhat/thermostat/gc/command/locale/strings.properties	Mon Oct 27 14:29:52 2014 -0400
@@ -0,0 +1,11 @@
+GCREQUEST_SERVICE_UNAVAILABLE = Unable to get GCRequest service
+GC_FAILED = Attempt to perform Garbage Collection failed
+HOST_SERVICE_UNAVAILABLE = Unable to get host information (HostInfoDAO is unavailable)
+VM_SERVICE_UNAVAILABLE = Unable to get vm information (VmInfoDAO is unavailable)
+AGENT_SERVICE_UNAVAILABLE = Unable to get agent information (AgentInfoDAO is unavailable)
+LISTENER_UNAVAILABLE = Unable to get listener
+VM_NOT_FOUND = VM with ID: {0} not found
+COMMAND_INTERRUPTED = Command interrupted while waiting for services.
+GC_ERROR_RESULT = GC Request Error for VM with PID: {0}
+GC_SUCCESS_RESULT = GC Successful for VM with PID: {0}
+GC_UNKNOWN_RESULT = Unknown result for GC request
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-gc/command/src/test/java/com/redhat/thermostat/vm/gc/command/internal/ActivatorTest.java	Mon Oct 27 14:29:52 2014 -0400
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2012-2014 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.vm.gc.command.internal;
+
+import static com.redhat.thermostat.testutils.Asserts.assertCommandIsRegistered;
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.testutils.StubBundleContext;
+
+public class ActivatorTest {
+    @Test
+    public void verifyCommandRegistered() throws Exception {
+        StubBundleContext context = new StubBundleContext();
+        Activator activator = new Activator();
+
+        activator.start(context);
+
+        assertCommandIsRegistered(context, "gc", GCCommand.class);
+
+        activator.stop(context);
+
+        assertEquals(0, context.getAllServices().size());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-gc/command/src/test/java/com/redhat/thermostat/vm/gc/command/internal/GCCommandListenerTest.java	Mon Oct 27 14:29:52 2014 -0400
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2012-2014 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.vm.gc.command.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.nio.charset.StandardCharsets;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import com.redhat.thermostat.common.command.Request;
+import com.redhat.thermostat.common.command.Response;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+
+public class GCCommandListenerTest {
+
+    private final GCCommandListener listener = new GCCommandListener();
+    private static final Logger logger = LoggingUtils
+            .getLogger(GCCommandListener.class);
+
+    private PrintStream ps;
+    private ByteArrayOutputStream baos;
+
+
+    @Before
+    public void setup() {
+        baos = new ByteArrayOutputStream();
+        ps = new PrintStream(baos);
+        listener.setOut(ps);
+        listener.setErr(ps);
+    }
+
+    @Test
+    public void testSuccessfulGCResponse() {
+        Request request = mock(Request.class);
+
+        Response resp = new Response(Response.ResponseType.OK);
+
+        Handler handler = mock(Handler.class);
+        logger.addHandler(handler);
+
+        final boolean[] complete = {false};
+        doAnswer(new Answer() {
+            @Override
+            public Object answer(InvocationOnMock invocation) throws Throwable {
+                LogRecord log = (LogRecord)invocation.getArguments()[0];
+                if (log.getLevel().equals(Level.INFO)) {
+                    complete[0] = true;
+                }
+                return null;
+            }
+        }).when(handler).publish(any(LogRecord.class));
+
+        listener.fireComplete(request, resp);
+
+        assertTrue(complete[0]);
+
+        String expected = "GC Successful for VM with PID: null\n";
+        assertEquals(expected, new String(baos.toByteArray(), StandardCharsets.UTF_8));
+    }
+
+    @Test
+    public void testErrorResponse() {
+        Request request = mock(Request.class);
+        Response resp = new Response(Response.ResponseType.ERROR);
+
+        Handler handler = mock(Handler.class);
+        logger.addHandler(handler);
+
+        final boolean[] complete = {false};
+        doAnswer(new Answer() {
+            @Override
+            public Object answer(InvocationOnMock invocation) throws Throwable {
+                LogRecord log = (LogRecord)invocation.getArguments()[0];
+                if (log.getLevel().equals(Level.SEVERE)) {
+                    complete[0] = true;
+                }
+                return null;
+            }
+        }).when(handler).publish(any(LogRecord.class));
+
+        listener.fireComplete(request, resp);
+
+        assertTrue(complete[0]);
+
+        String expected = "GC Request Error for VM with PID: null\n";
+        assertEquals(expected, new String(baos.toByteArray(), StandardCharsets.UTF_8));
+    }
+
+    @Test
+    public void testDefaultResponse() {
+        Request request = mock(Request.class);
+        Response resp = new Response(Response.ResponseType.NOK);
+
+        Handler handler = mock(Handler.class);
+        logger.addHandler(handler);
+
+        final boolean[] complete = {false};
+        doAnswer(new Answer() {
+            @Override
+            public Object answer(InvocationOnMock invocation) throws Throwable {
+                LogRecord log = (LogRecord)invocation.getArguments()[0];
+                if (log.getLevel().equals(Level.WARNING)) {
+                    complete[0] = true;
+                }
+                return null;
+            }
+        }).when(handler).publish(any(LogRecord.class));
+
+        listener.fireComplete(request, resp);
+
+        assertTrue(complete[0]);
+
+        assertTrue(baos.size() > 0);
+
+        String expected = "Unknown result for GC request\n";
+        assertEquals(expected, new String(baos.toByteArray(), StandardCharsets.UTF_8));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-gc/command/src/test/java/com/redhat/thermostat/vm/gc/command/internal/GCCommandTest.java	Mon Oct 27 14:29:52 2014 -0400
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2012-2014 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.vm.gc.command.internal;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import com.redhat.thermostat.common.cli.CommandContext;
+import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.common.cli.SimpleArguments;
+import com.redhat.thermostat.gc.remote.common.GCRequest;
+import com.redhat.thermostat.storage.core.HostRef;
+import com.redhat.thermostat.storage.core.VmId;
+import com.redhat.thermostat.storage.core.VmRef;
+import com.redhat.thermostat.storage.dao.AgentInfoDAO;
+import com.redhat.thermostat.storage.dao.HostInfoDAO;
+import com.redhat.thermostat.storage.dao.VmInfoDAO;
+import com.redhat.thermostat.storage.model.VmInfo;
+import com.redhat.thermostat.test.TestCommandContextFactory;
+
+public class GCCommandTest {
+
+    private GCCommand command;
+    private TestCommandContextFactory cmdCtxFactory;
+
+    private HostInfoDAO hostInfoDAO;
+    private VmInfoDAO vmInfoDAO;
+    private AgentInfoDAO agentInfoDAO;
+    private GCRequest gcRequest;
+    private GCCommandListener listener;
+
+    @Before
+    public void setup() {
+        cmdCtxFactory = new TestCommandContextFactory();
+
+        hostInfoDAO = mock(HostInfoDAO.class);
+        vmInfoDAO = mock(VmInfoDAO.class);
+        agentInfoDAO = mock(AgentInfoDAO.class);
+        gcRequest = mock(GCRequest.class);
+
+        listener = mock(GCCommandListener.class);
+
+        command = new GCCommand(listener);
+    }
+
+    @Test
+    public void testPerformGC() throws Exception {
+        String vmId = "liveVM";
+
+        VmRef vmRef = new VmRef(new HostRef(null, "dummy"), "liveVM", -1, "dummy");
+
+        VmInfo vmInfo = mock(VmInfo.class);
+        when(vmInfo.getVmPid()).thenReturn(-1);
+        when(vmInfo.getVmId()).thenReturn("liveVM");
+        when(vmInfo.getVmName()).thenReturn("dummy");
+
+        when(vmInfoDAO.getVmInfo(any(VmId.class))).thenReturn(vmInfo);
+
+        final boolean[] complete = {false};
+        doAnswer(new Answer() {
+            @Override
+            public Object answer(InvocationOnMock invocation) throws Throwable {
+                complete[0] = true;
+                return null;
+            }
+        }).when(gcRequest).sendGCRequestToAgent(vmRef, agentInfoDAO, listener);
+
+        CommandContext context = createVmIdArgs(vmId);
+
+        setServices();
+
+        command.run(context);
+
+        assertTrue(complete[0]);
+    }
+
+    @Test(expected = CommandException.class)
+    public void testPerformGCOnMissingVM() throws Exception {
+        String vmId = "nonexistentVM";
+
+        CommandContext context = createVmIdArgs(vmId);
+
+        setServices();
+
+        command.run(context);
+    }
+
+    @Test(expected = CommandException.class)
+    public void testGCWithoutServices() throws Exception {
+        String vmId = "liveVM";
+
+        CommandContext context = createVmIdArgs(vmId);
+
+        command.run(context);
+    }
+
+    private CommandContext createVmIdArgs(String vmId) {
+        SimpleArguments args = new SimpleArguments();
+        args.addArgument("vmId", vmId);
+        return cmdCtxFactory.createContext(args);
+    }
+
+    private void setServices() {
+        command.setServices(gcRequest, agentInfoDAO, hostInfoDAO, vmInfoDAO);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-gc/command/src/test/java/com/redhat/thermostat/vm/gc/command/locale/LocaleResourcesTest.java	Mon Oct 27 14:29:52 2014 -0400
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2012-2014 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.vm.gc.command.locale;
+
+import com.redhat.thermostat.testutils.AbstractLocaleResourcesTest;
+
+public class LocaleResourcesTest extends AbstractLocaleResourcesTest<LocaleResources> {
+    @Override
+    protected Class<LocaleResources> getEnumClass() {
+        return LocaleResources.class;
+    }
+
+    @Override
+    protected String getResourceBundle() {
+        return LocaleResources.RESOURCE_BUNDLE;
+    }
+}
--- a/vm-gc/distribution/pom.xml	Mon Oct 27 12:48:15 2014 -0400
+++ b/vm-gc/distribution/pom.xml	Mon Oct 27 14:29:52 2014 -0400
@@ -94,6 +94,11 @@
     </dependency>
     <dependency>
       <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-vm-gc-command</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
       <artifactId>thermostat-vm-gc-client-core</artifactId>
       <version>${project.version}</version>
     </dependency>
--- a/vm-gc/distribution/thermostat-plugin.xml	Mon Oct 27 12:48:15 2014 -0400
+++ b/vm-gc/distribution/thermostat-plugin.xml	Mon Oct 27 14:29:52 2014 -0400
@@ -39,6 +39,47 @@
 <plugin xmlns="http://icedtea.classpath.org/thermostat/plugins/v1.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://icedtea.classpath.org/thermostat/plugins/v1.0 thermostat-plugin.xsd">
+  <commands>
+    <command>
+      <name>gc</name>
+      <description>Performs Garbage Collection on the given vm</description>
+      <options>
+        <option>
+          <long>vmId</long>
+          <short>v</short>
+          <argument>vm</argument>
+          <required>true</required>
+          <description>the ID of the VM</description>
+        </option>
+      </options>
+      <environments>
+        <environment>cli</environment>
+        <environment>shell</environment>
+      </environments>
+      <bundles>
+        <bundle><symbolic-name>com.redhat.thermostat.vm.gc.command</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.gc.remote.client.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.gc.remote.common.command</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.common.command</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.client.core</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.client.command</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.client.cli</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.storage.mongodb</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.web.common</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>com.redhat.thermostat.web.client</symbolic-name><version>${project.version}</version></bundle>
+        <bundle><symbolic-name>org.mongodb.mongo-java-driver</symbolic-name><version>${mongo-driver.osgi-version}</version></bundle>
+        <bundle><symbolic-name>org.apache.commons.beanutils</symbolic-name><version>${commons-beanutils.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.commons.codec</symbolic-name><version>${commons-codec.osgi-version}</version></bundle>
+        <bundle><symbolic-name>org.apache.commons.collections</symbolic-name><version>${commons-collections.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.commons.logging</symbolic-name><version>${commons-logging.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.httpcomponents.httpcore</symbolic-name><version>${httpcomponents.core.version}</version></bundle>
+        <bundle><symbolic-name>org.apache.httpcomponents.httpclient</symbolic-name><version>${httpcomponents.client.version}</version></bundle>
+        <bundle><symbolic-name>${osgi.compendium.bundle.symbolic-name}</symbolic-name><version>${osgi.compendium.osgi-version}</version></bundle>
+        <bundle><symbolic-name>com.google.gson</symbolic-name><version>${gson.version}</version></bundle>
+        <bundle><symbolic-name>org.jboss.netty</symbolic-name><version>${netty.version}</version></bundle>
+      </bundles>
+    </command>
+  </commands>
   <extensions>
     <extension>
       <name>gui</name>
--- a/vm-gc/pom.xml	Mon Oct 27 12:48:15 2014 -0400
+++ b/vm-gc/pom.xml	Mon Oct 27 14:29:52 2014 -0400
@@ -54,6 +54,7 @@
     <module>agent</module>
     <module>client-core</module>
     <module>client-swing</module>
+    <module>command</module>
     <module>common</module>
     <module>distribution</module>
     <module>remote-collector-command</module>
--- a/vm-gc/remote-collector-client-common/src/main/java/com/redhat/thermostat/gc/remote/client/common/RequestGCAction.java	Mon Oct 27 12:48:15 2014 -0400
+++ b/vm-gc/remote-collector-client-common/src/main/java/com/redhat/thermostat/gc/remote/client/common/RequestGCAction.java	Mon Oct 27 14:29:52 2014 -0400
@@ -38,26 +38,26 @@
 
 import com.redhat.thermostat.common.ActionListener;
 import com.redhat.thermostat.common.ActionNotifier;
-import com.redhat.thermostat.gc.remote.common.command.GCCommand;
+import com.redhat.thermostat.gc.remote.common.command.GCAction;
 
 public class RequestGCAction {
     
-    private final ActionNotifier<GCCommand> notifier;
+    private final ActionNotifier<GCAction> notifier;
     
     public RequestGCAction() {
         notifier = new ActionNotifier<>(this);
     }
     
-    public void addActionListener(ActionListener<GCCommand> listener) {
+    public void addActionListener(ActionListener<GCAction> listener) {
         this.notifier.addActionListener(listener);
     }
     
-    public void removeActionListener(ActionListener<GCCommand> listener) {
+    public void removeActionListener(ActionListener<GCAction> listener) {
         this.notifier.removeActionListener(listener);
     }
     
     public void requestGC() {
-        notifier.fireAction(GCCommand.REQUEST_GC);
+        notifier.fireAction(GCAction.REQUEST_GC);
     }
 }
 
--- a/vm-gc/remote-collector-client-common/src/main/java/com/redhat/thermostat/gc/remote/common/GCRequest.java	Mon Oct 27 12:48:15 2014 -0400
+++ b/vm-gc/remote-collector-client-common/src/main/java/com/redhat/thermostat/gc/remote/common/GCRequest.java	Mon Oct 27 14:29:52 2014 -0400
@@ -42,7 +42,7 @@
 import com.redhat.thermostat.common.command.Request;
 import com.redhat.thermostat.common.command.Request.RequestType;
 import com.redhat.thermostat.common.command.RequestResponseListener;
-import com.redhat.thermostat.gc.remote.common.command.GCCommand;
+import com.redhat.thermostat.gc.remote.common.command.GCAction;
 import com.redhat.thermostat.storage.core.HostRef;
 import com.redhat.thermostat.storage.core.VmRef;
 import com.redhat.thermostat.storage.dao.AgentInfoDAO;
@@ -66,11 +66,11 @@
         InetSocketAddress target = new InetSocketAddress(host[0], Integer.parseInt(host[1]));
         Request gcRequest = createRequest(target);
 
-        gcRequest.setReceiver(GCCommand.RECEIVER);
+        gcRequest.setReceiver(GCAction.RECEIVER);
 
         gcRequest.setParameter(Request.ACTION, CMD_CHANNEL_ACTION_NAME);
-        gcRequest.setParameter(GCCommand.class.getName(), GCCommand.REQUEST_GC.name());
-        gcRequest.setParameter(GCCommand.VM_PID, String.valueOf(vm.getPid()));
+        gcRequest.setParameter(GCAction.class.getName(), GCAction.REQUEST_GC.name());
+        gcRequest.setParameter(GCAction.VM_PID, String.valueOf(vm.getPid()));
         
         gcRequest.addListener(responseListener);
 
--- a/vm-gc/remote-collector-client-common/src/test/java/com/redhat/thermostat/gc/remote/common/GCRequestTest.java	Mon Oct 27 12:48:15 2014 -0400
+++ b/vm-gc/remote-collector-client-common/src/test/java/com/redhat/thermostat/gc/remote/common/GCRequestTest.java	Mon Oct 27 14:29:52 2014 -0400
@@ -49,7 +49,7 @@
 import com.redhat.thermostat.client.command.RequestQueue;
 import com.redhat.thermostat.common.command.Request;
 import com.redhat.thermostat.common.command.RequestResponseListener;
-import com.redhat.thermostat.gc.remote.common.command.GCCommand;
+import com.redhat.thermostat.gc.remote.common.command.GCAction;
 import com.redhat.thermostat.storage.core.HostRef;
 import com.redhat.thermostat.storage.core.VmRef;
 import com.redhat.thermostat.storage.dao.AgentInfoDAO;
@@ -113,9 +113,9 @@
         assertTrue(results[1]);
         assertTrue(results[2]);
         
-        verify(request).setReceiver(GCCommand.RECEIVER);
-        verify(request).setParameter(GCCommand.class.getName(), GCCommand.REQUEST_GC.name());
-        verify(request).setParameter(GCCommand.VM_PID, "123456");
+        verify(request).setReceiver(GCAction.RECEIVER);
+        verify(request).setParameter(GCAction.class.getName(), GCAction.REQUEST_GC.name());
+        verify(request).setParameter(GCAction.VM_PID, "123456");
         verify(request).addListener(listener);
         
         verify(queue).putRequest(request);
--- a/vm-gc/remote-collector-command/pom.xml	Mon Oct 27 12:48:15 2014 -0400
+++ b/vm-gc/remote-collector-command/pom.xml	Mon Oct 27 14:29:52 2014 -0400
@@ -88,7 +88,12 @@
       <artifactId>thermostat-agent-core</artifactId>
       <version>${project.version}</version>      
     </dependency>
-            
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-common-test</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>
@@ -101,7 +106,7 @@
           <instructions>
             <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
             <Bundle-SymbolicName>com.redhat.thermostat.gc.remote.command</Bundle-SymbolicName>
-            <Bundle-Activator>com.redhat.thermostat.gc.remote.command.osgi.GCCommandReceiverActivator</Bundle-Activator>            
+            <Bundle-Activator>com.redhat.thermostat.gc.remote.command.osgi.Activator</Bundle-Activator>
             <Export-Package>
               com.redhat.thermostat.gc.remote.command,
             </Export-Package>
--- a/vm-gc/remote-collector-command/src/main/java/com/redhat/thermostat/gc/remote/command/GCCommandReceiver.java	Mon Oct 27 12:48:15 2014 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-/*
- * Copyright 2012-2014 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.gc.remote.command;
-
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.redhat.thermostat.agent.command.RequestReceiver;
-import com.redhat.thermostat.agent.utils.management.MXBeanConnectionPool;
-import com.redhat.thermostat.common.command.Request;
-import com.redhat.thermostat.common.command.Response;
-import com.redhat.thermostat.common.command.Response.ResponseType;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-import com.redhat.thermostat.gc.remote.command.internal.GC;
-import com.redhat.thermostat.gc.remote.command.internal.GCException;
-import com.redhat.thermostat.gc.remote.common.command.GCCommand;
-
-public class GCCommandReceiver implements RequestReceiver {
-
-    private static final Logger logger = LoggingUtils.getLogger(GCCommandReceiver.class);
-    private MXBeanConnectionPool pool;
-
-    public GCCommandReceiver(MXBeanConnectionPool pool) {
-        this.pool = pool;
-    }
-
-    @Override
-    public Response receive(Request request) {
-        Response response = new Response(ResponseType.OK);
-        
-        String command = request.getParameter(GCCommand.class.getName());
-        switch (GCCommand.valueOf(command)) {
-        case REQUEST_GC:
-            String strPid = request.getParameter(GCCommand.VM_PID);
-            try {
-                int vmId = Integer.parseInt(strPid);
-                new GC(pool, vmId).gc();
-            } catch (GCException gce) {
-                response = new Response(ResponseType.ERROR);
-                logger.log(Level.WARNING, "GC request failed", gce);
-            } catch (NumberFormatException e) {
-                response = new Response(ResponseType.ERROR);
-                logger.log(Level.WARNING, "Invalid PID: " + strPid, e);
-            }
-            break;
-        default:
-            break;
-        }
-        return response;
-    }
-}
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-gc/remote-collector-command/src/main/java/com/redhat/thermostat/gc/remote/command/GCRequestReceiver.java	Mon Oct 27 14:29:52 2014 -0400
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2012-2014 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.gc.remote.command;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.redhat.thermostat.agent.command.RequestReceiver;
+import com.redhat.thermostat.agent.utils.management.MXBeanConnectionPool;
+import com.redhat.thermostat.common.command.Request;
+import com.redhat.thermostat.common.command.Response;
+import com.redhat.thermostat.common.command.Response.ResponseType;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+import com.redhat.thermostat.gc.remote.command.internal.GC;
+import com.redhat.thermostat.gc.remote.command.internal.GCException;
+import com.redhat.thermostat.gc.remote.common.command.GCAction;
+
+public class GCRequestReceiver implements RequestReceiver {
+
+    private static final Logger logger = LoggingUtils.getLogger(GCRequestReceiver.class);
+    private MXBeanConnectionPool pool;
+
+    public GCRequestReceiver(MXBeanConnectionPool pool) {
+        this.pool = pool;
+    }
+
+    @Override
+    public Response receive(Request request) {
+        Response response = new Response(ResponseType.OK);
+        
+        String command = request.getParameter(GCAction.class.getName());
+        switch (GCAction.valueOf(command)) {
+        case REQUEST_GC:
+            String strPid = request.getParameter(GCAction.VM_PID);
+            try {
+                int vmId = Integer.parseInt(strPid);
+                new GC(pool, vmId).gc();
+            } catch (GCException gce) {
+                response = new Response(ResponseType.ERROR);
+                logger.log(Level.WARNING, "GC request failed", gce);
+            } catch (NumberFormatException e) {
+                response = new Response(ResponseType.ERROR);
+                logger.log(Level.WARNING, "Invalid PID: " + strPid, e);
+            }
+            break;
+        default:
+            break;
+        }
+        return response;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-gc/remote-collector-command/src/main/java/com/redhat/thermostat/gc/remote/command/osgi/Activator.java	Mon Oct 27 14:29:52 2014 -0400
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2012-2014 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.gc.remote.command.osgi;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+
+import com.redhat.thermostat.agent.command.ReceiverRegistry;
+import com.redhat.thermostat.agent.utils.management.MXBeanConnectionPool;
+import com.redhat.thermostat.gc.remote.command.GCRequestReceiver;
+
+public class Activator implements BundleActivator {
+
+    private ServiceTracker tracker;
+
+    @Override
+    public void start(BundleContext context) throws Exception {
+        final ReceiverRegistry registry = new ReceiverRegistry(context);
+
+        tracker = new ServiceTracker(context, MXBeanConnectionPool.class, null) {
+            @Override
+            public MXBeanConnectionPool addingService(ServiceReference reference) {
+                MXBeanConnectionPool pool = (MXBeanConnectionPool) super.addingService(reference);
+                registry.registerReceiver(new GCRequestReceiver(pool));
+                return pool;
+            };
+
+            @Override
+            public void removedService(ServiceReference reference, Object service) {
+                registry.unregisterReceivers();
+                super.removedService(reference, service);
+            };
+        };
+        tracker.open();
+    }
+
+    @Override
+    public void stop(BundleContext context) throws Exception {
+        tracker.close();
+    }
+}
+
--- a/vm-gc/remote-collector-command/src/main/java/com/redhat/thermostat/gc/remote/command/osgi/GCCommandReceiverActivator.java	Mon Oct 27 12:48:15 2014 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * Copyright 2012-2014 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.gc.remote.command.osgi;
-
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.osgi.util.tracker.ServiceTracker;
-
-import com.redhat.thermostat.agent.command.ReceiverRegistry;
-import com.redhat.thermostat.agent.utils.management.MXBeanConnectionPool;
-import com.redhat.thermostat.gc.remote.command.GCCommandReceiver;
-
-public class GCCommandReceiverActivator implements BundleActivator {
-
-    ServiceTracker tracker;
-
-    @Override
-    public void start(BundleContext context) throws Exception {
-        final ReceiverRegistry registry = new ReceiverRegistry(context);
-
-        tracker = new ServiceTracker(context, MXBeanConnectionPool.class, null) {
-            public MXBeanConnectionPool addingService(ServiceReference reference) {
-                MXBeanConnectionPool pool = (MXBeanConnectionPool) super.addingService(reference);
-                registry.registerReceiver(new GCCommandReceiver(pool));
-                return pool;
-            };
-
-            public void removedService(org.osgi.framework.ServiceReference reference, Object service) {
-                registry.unregisterReceivers();
-                super.removedService(reference, service);
-            };
-        };
-        tracker.open();
-    }
-
-    @Override
-    public void stop(BundleContext context) throws Exception {
-        tracker.close();
-    }
-}
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-gc/remote-collector-command/src/test/java/com/redhat/thermostat/gc/remote/command/osgi/ActivatorTest.java	Mon Oct 27 14:29:52 2014 -0400
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2012-2014 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.gc.remote.command.osgi;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.agent.command.RequestReceiver;
+import com.redhat.thermostat.agent.utils.management.MXBeanConnectionPool;
+import com.redhat.thermostat.gc.remote.command.GCRequestReceiver;
+import com.redhat.thermostat.testutils.StubBundleContext;
+
+public class ActivatorTest {
+
+    private StubBundleContext context;
+    private Activator activator;
+
+    @Before
+    public void setup() {
+        context = new StubBundleContext();
+        activator = new Activator();
+    }
+
+    @Test
+    public void verifyReceiverRegistered() throws Exception {
+        MXBeanConnectionPool mxBeanConnectionPool = mock(MXBeanConnectionPool.class);
+        context.registerService(MXBeanConnectionPool.class, mxBeanConnectionPool, null);
+
+        activator.start(context);
+
+        assertEquals(2, context.getAllServices().size());
+        assertTrue(context.isServiceRegistered(RequestReceiver.class.getName(), GCRequestReceiver.class));
+
+        activator.stop(context);
+    }
+
+    @Test
+    public void verifyActivatorDoesNotRegisterServiceOnMissingDeps() throws Exception {
+        activator.start(context);
+
+        assertEquals(0, context.getAllServices().size());
+
+        activator.stop(context);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-gc/remote-collector-common/src/main/java/com/redhat/thermostat/gc/remote/common/command/GCAction.java	Mon Oct 27 14:29:52 2014 -0400
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2012-2014 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.gc.remote.common.command;
+
+public enum GCAction {
+
+    REQUEST_GC;
+    
+    public static final String VM_PID = "VM_PID";
+    public static final String RECEIVER = "com.redhat.thermostat.gc.remote.command.GCRequestReceiver";
+}
+
--- a/vm-gc/remote-collector-common/src/main/java/com/redhat/thermostat/gc/remote/common/command/GCCommand.java	Mon Oct 27 12:48:15 2014 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright 2012-2014 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.gc.remote.common.command;
-
-public enum GCCommand {
-
-    REQUEST_GC;
-    
-    public static final String VM_PID = "VM_PID";
-    public static final String RECEIVER = "com.redhat.thermostat.gc.remote.command.GCCommandReceiver";
-}
-
--- a/vm-memory/client-core/src/main/java/com/redhat/thermostat/vm/memory/client/core/MemoryStatsView.java	Mon Oct 27 12:48:15 2014 -0400
+++ b/vm-memory/client-core/src/main/java/com/redhat/thermostat/vm/memory/client/core/MemoryStatsView.java	Mon Oct 27 14:29:52 2014 -0400
@@ -39,7 +39,7 @@
 import com.redhat.thermostat.client.core.views.BasicView;
 import com.redhat.thermostat.client.core.views.UIComponent;
 import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.gc.remote.common.command.GCCommand;
+import com.redhat.thermostat.gc.remote.common.command.GCAction;
 import com.redhat.thermostat.shared.locale.LocalizedString;
 
 public abstract class MemoryStatsView extends BasicView implements UIComponent {
@@ -48,7 +48,7 @@
     public abstract void updateRegion(Payload region);
     
     public abstract void setEnableGCAction(boolean enable);
-    public abstract void addGCActionListener(ActionListener<GCCommand> listener);
+    public abstract void addGCActionListener(ActionListener<GCAction> listener);
     
     public abstract void requestRepaint();
 
--- a/vm-memory/client-core/src/main/java/com/redhat/thermostat/vm/memory/client/core/internal/MemoryStatsController.java	Mon Oct 27 12:48:15 2014 -0400
+++ b/vm-memory/client-core/src/main/java/com/redhat/thermostat/vm/memory/client/core/internal/MemoryStatsController.java	Mon Oct 27 14:29:52 2014 -0400
@@ -57,7 +57,7 @@
 import com.redhat.thermostat.common.command.Response;
 import com.redhat.thermostat.common.command.Response.ResponseType;
 import com.redhat.thermostat.gc.remote.common.GCRequest;
-import com.redhat.thermostat.gc.remote.common.command.GCCommand;
+import com.redhat.thermostat.gc.remote.common.command.GCAction;
 import com.redhat.thermostat.shared.locale.LocalizedString;
 import com.redhat.thermostat.shared.locale.Translate;
 import com.redhat.thermostat.storage.core.VmRef;
@@ -192,9 +192,9 @@
             }
         });
         
-        view.addGCActionListener(new ActionListener<GCCommand>() {
+        view.addGCActionListener(new ActionListener<GCAction>() {
             @Override
-            public void actionPerformed(ActionEvent<GCCommand> actionEvent) {
+            public void actionPerformed(ActionEvent<GCAction> actionEvent) {
                 RequestResponseListener listener = new RequestResponseListener() {
                     @Override
                     public void fireComplete(Request request, Response response) {
--- a/vm-memory/client-core/src/test/java/com/redhat/thermostat/vm/memory/client/core/internal/MemoryStatsControllerTest.java	Mon Oct 27 12:48:15 2014 -0400
+++ b/vm-memory/client-core/src/test/java/com/redhat/thermostat/vm/memory/client/core/internal/MemoryStatsControllerTest.java	Mon Oct 27 14:29:52 2014 -0400
@@ -66,7 +66,7 @@
 import com.redhat.thermostat.common.TimerFactory;
 import com.redhat.thermostat.common.command.RequestResponseListener;
 import com.redhat.thermostat.gc.remote.common.GCRequest;
-import com.redhat.thermostat.gc.remote.common.command.GCCommand;
+import com.redhat.thermostat.gc.remote.common.command.GCAction;
 import com.redhat.thermostat.storage.core.VmRef;
 import com.redhat.thermostat.storage.dao.AgentInfoDAO;
 import com.redhat.thermostat.storage.dao.VmInfoDAO;
@@ -89,7 +89,7 @@
     private Timer timer;
     
     private ActionListener<MemoryStatsView.Action> viewListener;
-    private ActionListener<GCCommand> gcActionListener;
+    private ActionListener<GCAction> gcActionListener;
 
     private MemoryStatsController controller;
     
@@ -204,7 +204,7 @@
 
     @Test
     public void testGCInvoked() {
-        gcActionListener.actionPerformed(new ActionEvent<>(view, GCCommand.REQUEST_GC));
+        gcActionListener.actionPerformed(new ActionEvent<>(view, GCAction.REQUEST_GC));
         verify(gcRequest).sendGCRequestToAgent(eq(ref), eq(agentDAO), isA(RequestResponseListener.class));
     }
     
--- a/vm-memory/client-swing/src/main/java/com/redhat/thermostat/vm/memory/client/swing/internal/MemoryStatsViewImpl.java	Mon Oct 27 12:48:15 2014 -0400
+++ b/vm-memory/client-swing/src/main/java/com/redhat/thermostat/vm/memory/client/swing/internal/MemoryStatsViewImpl.java	Mon Oct 27 14:29:52 2014 -0400
@@ -55,7 +55,7 @@
 import com.redhat.thermostat.common.ActionListener;
 import com.redhat.thermostat.gc.remote.client.common.RequestGCAction;
 import com.redhat.thermostat.gc.remote.client.swing.ToolbarGCButton;
-import com.redhat.thermostat.gc.remote.common.command.GCCommand;
+import com.redhat.thermostat.gc.remote.common.command.GCAction;
 import com.redhat.thermostat.shared.locale.LocalizedString;
 import com.redhat.thermostat.shared.locale.Translate;
 import com.redhat.thermostat.vm.memory.client.core.MemoryStatsView;
@@ -138,7 +138,7 @@
     }
 
     @Override
-    public void addGCActionListener(ActionListener<GCCommand> listener) {
+    public void addGCActionListener(ActionListener<GCAction> listener) {
         toolbarButtonAction.addActionListener(listener);
     }