changeset 2771:1a0d260468d1

Initial JCMD Plugin review-thread: http://icedtea.classpath.org/pipermail/thermostat/2017-September/025195.html reviewed-by: stooke
author Mario Torre <neugens.limasoftware@gmail.com>
date Mon, 09 Oct 2017 15:56:10 +0200
parents bde0a709ca30
children 9e3d6eedbbee
files distribution/assembly/plugin-assembly.xml distribution/pom.xml plugins/jcmd-stats-collector/agent/pom.xml plugins/jcmd-stats-collector/agent/src/main/java/com/redhat/thermostat/agent/jcmd/backend/internal/JCMDBackend.java plugins/jcmd-stats-collector/agent/src/main/java/com/redhat/thermostat/agent/jcmd/backend/internal/JMXConnectionManager.java plugins/jcmd-stats-collector/agent/src/main/java/com/redhat/thermostat/agent/jcmd/backend/internal/JMXReceiver.java plugins/jcmd-stats-collector/agent/src/main/java/com/redhat/thermostat/agent/jcmd/backend/internal/NetworkHandler.java plugins/jcmd-stats-collector/agent/src/main/java/com/redhat/thermostat/agent/jcmd/backend/internal/model/GCStatsModel.java plugins/jcmd-stats-collector/agent/src/main/java/com/redhat/thermostat/agent/jcmd/backend/internal/model/JCMDBinding.java plugins/jcmd-stats-collector/agent/src/test/java/com/redhat/thermostat/agent/jcmd/backend/internal/JCMDBackendTest.java plugins/jcmd-stats-collector/agent/src/test/java/com/redhat/thermostat/agent/jcmd/backend/internal/JMXReceiverTest.java plugins/jcmd-stats-collector/agent/src/test/java/com/redhat/thermostat/agent/jcmd/backend/internal/model/JCMDBindingTest.java plugins/jcmd-stats-collector/distribution/assemblies/plugin-assembly.xml plugins/jcmd-stats-collector/distribution/configFiles/gateway.properties plugins/jcmd-stats-collector/distribution/pom.xml plugins/jcmd-stats-collector/distribution/thermostat-plugin.xml plugins/jcmd-stats-collector/pom.xml plugins/jvm-overview/pom.xml.orig plugins/pom.xml
diffstat 19 files changed, 1340 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/distribution/assembly/plugin-assembly.xml	Fri Oct 06 14:14:13 2017 -0400
+++ b/distribution/assembly/plugin-assembly.xml	Mon Oct 09 15:56:10 2017 +0200
@@ -61,6 +61,7 @@
         <include>com.redhat.thermostat.agent:thermostat-commands-distribution</include>
         <include>com.redhat.thermostat.agent:thermostat-killvm-distribution</include>
         <include>com.redhat.thermostat.agent:thermostat-vm-compiler-distribution</include>
+	    <include>com.redhat.thermostat.agent:thermostat-jcmd-stats-collector-distribution</include>
         <!--        <include>com.redhat.thermostat.agent:thermostat-numa-distribution</include>-->
 <!--        <include>com.redhat.thermostat.agent:thermostat-thread-distribution</include>-->
 <!--        <include>com.redhat.thermostat.agent:thermostat-vm-classstat-distribution</include>-->
--- a/distribution/pom.xml	Fri Oct 06 14:14:13 2017 -0400
+++ b/distribution/pom.xml	Mon Oct 09 15:56:10 2017 +0200
@@ -466,6 +466,12 @@
     </dependency>
     <dependency>
       <groupId>com.redhat.thermostat.agent</groupId>
+      <artifactId>thermostat-jcmd-stats-collector-distribution</artifactId>
+      <version>${project.version}</version>
+      <type>zip</type>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat.agent</groupId>
       <artifactId>thermostat-host-cpu-distribution</artifactId>
       <version>${project.version}</version>
       <type>zip</type>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/jcmd-stats-collector/agent/pom.xml	Mon Oct 09 15:56:10 2017 +0200
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright 2012-2017 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>
+    <artifactId>thermostat-jcmd-stats-collector</artifactId>
+    <groupId>com.redhat.thermostat.agent</groupId>
+    <version>2.99.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>thermostat-jcmd-stats-collector-agent</artifactId>
+  <packaging>bundle</packaging>
+  <name>Thermostat JCMD Stats Collector Agent plugin</name>
+
+  <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.agent.jcmd</Bundle-SymbolicName>
+            <Private-Package>
+              com.redhat.thermostat.agent.jcmd.backend.internal,
+              com.redhat.thermostat.agent.jcmd.backend.internal.model,
+            </Private-Package>
+            <!-- Do not autogenerate uses clauses in Manifests -->
+            <_nouses>true</_nouses>
+          </instructions>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-scr-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>generate-scr-scrdescriptor</id>
+            <goals>
+              <goal>scr</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+
+
+    </plugins>
+  </build>
+
+  <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>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.agent</groupId>
+      <artifactId>thermostat-common-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat.agent</groupId>
+      <artifactId>thermostat-common-plugin</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat.agent</groupId>
+      <artifactId>thermostat-common-portability</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat.agent</groupId>
+      <artifactId>thermostat-agent-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat.agent</groupId>
+      <artifactId>thermostat-storage-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat.agent</groupId>
+      <artifactId>thermostat-jvm-overview-agent</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat.agent</groupId>
+      <artifactId>thermostat-commands-agent</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat.agent</groupId>
+      <artifactId>thermostat-common-test</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <!-- declarative services -->
+    <dependency>
+      <groupId>org.apache.felix</groupId>
+      <artifactId>org.apache.felix.scr.annotations</artifactId>
+    </dependency>
+  </dependencies>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/jcmd-stats-collector/agent/src/main/java/com/redhat/thermostat/agent/jcmd/backend/internal/JCMDBackend.java	Mon Oct 09 15:56:10 2017 +0200
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent.jcmd.backend.internal;
+
+import com.redhat.thermostat.agent.http.HttpRequestService;
+import com.redhat.thermostat.agent.utils.management.MXBeanConnectionPool;
+import com.redhat.thermostat.backend.Backend;
+import com.redhat.thermostat.backend.BaseBackend;
+import com.redhat.thermostat.commands.agent.receiver.RequestReceiver;
+
+import com.redhat.thermostat.common.config.experimental.ConfigurationInfoSource;
+import com.redhat.thermostat.jvm.overview.agent.model.VmMapperService;
+import com.redhat.thermostat.lang.schema.JSONService;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.Service;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+@Component
+@Service(value = Backend.class)
+public class JCMDBackend extends BaseBackend {
+
+    private boolean enabled = false;
+
+    private ServiceRegistration<RequestReceiver> reg;
+    private JMXReceiver receiver;
+    private JMXConnectionManager connectionManager;
+
+    private BundleContext context;
+
+    @Reference
+    private MXBeanConnectionPool mxBeanPool;
+
+    @Reference
+    private JSONService json;
+
+    @Reference
+    private HttpRequestService httpRequestService;
+
+    @Reference
+    private ConfigurationInfoSource configInfoSource;
+
+    @Reference
+    private VmMapperService mapperService;
+
+    public JCMDBackend() {
+        super("JCMD Stats Collector Backend",
+              "Gathers stats from JVM with diagnostic options enabled",
+              "Red Hat, Inc.");
+    }
+
+    @Activate
+    void _activate_(BundleContext context) {
+        this.context = context;
+        if (connectionManager == null) {
+            connectionManager = new JMXConnectionManager(mxBeanPool);
+            NetworkHandler networkHandler = new NetworkHandler(httpRequestService, configInfoSource);
+            receiver = new JMXReceiver(connectionManager, json, mapperService, networkHandler);
+        }
+    }
+
+    @Deactivate
+    private void _deactivate_(BundleContext context) {
+        if (reg != null) {
+            reg.unregister();
+            reg = null;
+        }
+    }
+
+    @Override
+    public boolean activate() {
+        enabled = true;
+
+        if (reg == null) {
+            Dictionary<String, Object> serviceProperties = new Hashtable<>();
+            serviceProperties.put("servicename", "jcmd");
+            reg = context.registerService(RequestReceiver.class, receiver, serviceProperties);
+        }
+
+        return true;
+    }
+
+    @Override
+    public boolean deactivate() {
+        enabled = false;
+        _deactivate_(this.context);
+        return true;
+    }
+
+    @Override
+    public boolean isActive() {
+        return enabled;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/jcmd-stats-collector/agent/src/main/java/com/redhat/thermostat/agent/jcmd/backend/internal/JMXConnectionManager.java	Mon Oct 09 15:56:10 2017 +0200
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent.jcmd.backend.internal;
+
+import com.redhat.thermostat.agent.utils.management.MXBeanConnection;
+import com.redhat.thermostat.agent.utils.management.MXBeanConnectionPool;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+import com.redhat.thermostat.agent.jcmd.backend.internal.model.JCMDBinding;
+import com.redhat.thermostat.lang.schema.models.Pid;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Logger;
+
+public class JMXConnectionManager {
+    private static final Logger log = LoggingUtils.getLogger(JMXConnectionManager.class);
+
+    private Map<Pid, JCMDBinding> connections;
+    private MXBeanConnectionPool mxBeanPool;
+
+    JMXConnectionManager(Map<Pid, JCMDBinding> connections, MXBeanConnectionPool mxBeanPool) {
+        this.connections = connections;
+        this.mxBeanPool = mxBeanPool;
+    }
+
+    JMXConnectionManager(MXBeanConnectionPool mxBeanPool) {
+        this(new HashMap<Pid, JCMDBinding>(), mxBeanPool);
+    }
+
+    public JCMDBinding getBindings(Pid pid) throws Exception {
+
+        if (connections.containsKey(pid)) {
+            return connections.get(pid);
+        }
+
+        try {
+            MXBeanConnection connection = mxBeanPool.acquire(pid.get());
+
+            JCMDBinding binding = new JCMDBinding(connection);
+
+            if (binding.canCollectDiagnosticData()) {
+                connections.put(pid, binding);
+
+            } else {
+                log.warning("vm does not run with -XX:+UnlockDiagnosticVMOptions");
+                mxBeanPool.release(pid.get(), connection);
+                throw new UnsupportedOperationException("vm does not run with +UnlockDiagnosticVMOptions");
+            }
+
+            return binding;
+
+        } catch (NumberFormatException nfe) {
+            log.warning("vm-pid cannot be parsed: " + pid);
+            throw nfe;
+        }
+    }
+
+    public void release(Pid pid) {
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/jcmd-stats-collector/agent/src/main/java/com/redhat/thermostat/agent/jcmd/backend/internal/JMXReceiver.java	Mon Oct 09 15:56:10 2017 +0200
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent.jcmd.backend.internal;
+
+import com.redhat.thermostat.commands.agent.receiver.RequestReceiver;
+import com.redhat.thermostat.commands.model.AgentRequest;
+import com.redhat.thermostat.commands.model.WebSocketResponse;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+import com.redhat.thermostat.agent.jcmd.backend.internal.model.GCStatsModel;
+import com.redhat.thermostat.agent.jcmd.backend.internal.model.JCMDBinding;
+import com.redhat.thermostat.jvm.overview.agent.model.VmMapperService;
+import com.redhat.thermostat.lang.schema.JSONService;
+import com.redhat.thermostat.lang.schema.models.Pid;
+import com.redhat.thermostat.lang.schema.models.Timestamp;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+class JMXReceiver implements RequestReceiver {
+
+    private static final Logger log = LoggingUtils.getLogger(JMXReceiver.class);
+
+    private JMXConnectionManager connectionManager;
+    private JSONService json;
+    private NetworkHandler networkHandler;
+    private VmMapperService mapperService;
+
+    public JMXReceiver(JMXConnectionManager connectionManager, JSONService json,
+                       VmMapperService mapperService, NetworkHandler networkHandler)
+    {
+        this.connectionManager = connectionManager;
+        this.json = json;
+        this.networkHandler = networkHandler;
+        this.mapperService = mapperService;
+    }
+
+    @Override
+    public WebSocketResponse receive(AgentRequest request) {
+
+        WebSocketResponse.ResponseType responseType = WebSocketResponse.ResponseType.ERROR;
+        String vmId = request.getJvmId();
+        Pid pid = mapperService.getPid(vmId);
+        if (pid == null) {
+            return new WebSocketResponse(request.getSequenceId(), responseType);
+        }
+
+        try {
+            JCMDBinding binding = connectionManager.getBindings(pid);
+
+            Timestamp timestamp = new Timestamp(System.currentTimeMillis());
+            String gcStats = binding.getGCStats();
+
+            // enable for debugging, this prints a lot of output
+//            log.log(Level.WARNING, "gcStats follow ----------");
+//            log.log(Level.WARNING, gcStats);
+//            log.log(Level.WARNING, "gcStats follow end ------");
+
+            GCStatsModel model = new GCStatsModel(timestamp, gcStats);
+            String serialisedModel = json.serialiase(model);
+
+            responseType = networkHandler.send(serialisedModel, request.getSystemId(), vmId);
+
+        } catch (Exception ex) {
+            log.log(Level.WARNING, "Error!" , ex);
+            responseType = WebSocketResponse.ResponseType.ERROR;
+        }
+
+        return new WebSocketResponse(request.getSequenceId(), responseType);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/jcmd-stats-collector/agent/src/main/java/com/redhat/thermostat/agent/jcmd/backend/internal/NetworkHandler.java	Mon Oct 09 15:56:10 2017 +0200
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent.jcmd.backend.internal;
+
+import com.redhat.thermostat.agent.http.HttpRequestService;
+import com.redhat.thermostat.commands.model.WebSocketResponse;
+import com.redhat.thermostat.common.config.experimental.ConfigurationInfoSource;
+import com.redhat.thermostat.common.plugin.PluginConfiguration;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class NetworkHandler {
+    private static final String PLUGIN_ID = "jcmd";
+    private static final String SYSTEM_PATH = "systems/";
+    private static final String VM_PATH = "/jvms/";
+
+    private HttpRequestService httpRequestService;
+
+    private PluginConfiguration configuration;
+
+    public NetworkHandler(HttpRequestService httpRequestService, ConfigurationInfoSource configInfoSource)
+    {
+        this.httpRequestService = httpRequestService;
+        this.configuration = new ConfigurationCreator().create(configInfoSource);
+    }
+
+    private URI getURI(String systemId, String vmId) throws IOException {
+        StringBuilder builder = new StringBuilder();
+        builder.append(SYSTEM_PATH);
+        builder.append(systemId);
+        builder.append(VM_PATH);
+        builder.append(vmId);
+        return configuration.getGatewayURL().resolve(builder.toString());
+    }
+
+    public WebSocketResponse.ResponseType send(String serialisedModel, String systemId, String vmId) throws Exception {
+        //Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "jvmid: " + vmId + ", body: " + serialisedModel);
+        httpRequestService.sendHttpRequest(serialisedModel, getURI(systemId, vmId), HttpRequestService.Method.POST);
+        return WebSocketResponse.ResponseType.OK;
+    }
+
+    static class ConfigurationCreator {
+
+        PluginConfiguration create(ConfigurationInfoSource source) {
+            return new PluginConfiguration(source, PLUGIN_ID);
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/jcmd-stats-collector/agent/src/main/java/com/redhat/thermostat/agent/jcmd/backend/internal/model/GCStatsModel.java	Mon Oct 09 15:56:10 2017 +0200
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent.jcmd.backend.internal.model;
+
+import com.redhat.thermostat.lang.schema.annotations.Schema;
+import com.redhat.thermostat.lang.schema.annotations.Type;
+import com.redhat.thermostat.lang.schema.models.Timestamp;
+
+@Type(description = "Full JCMD GC.class_stats data dump")
+public class GCStatsModel {
+    @Schema(description = "The timestamp the request was made", required = true)
+    private Timestamp timestamp;
+
+    @Schema(description = "The data dump", required = true)
+    private String payload;
+
+    public GCStatsModel(Timestamp timestamp, String payload) {
+        this.timestamp = timestamp;
+        this.payload = payload;
+    }
+
+    public String getPayload() {
+        return payload;
+    }
+
+    public Timestamp getTimestamp() {
+        return timestamp;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/jcmd-stats-collector/agent/src/main/java/com/redhat/thermostat/agent/jcmd/backend/internal/model/JCMDBinding.java	Mon Oct 09 15:56:10 2017 +0200
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent.jcmd.backend.internal.model;
+
+import com.redhat.thermostat.agent.utils.management.MXBeanConnection;
+
+import javax.management.ObjectName;
+
+public class JCMDBinding {
+
+    private MXBeanConnection connection;
+
+    public JCMDBinding(MXBeanConnection connection) {
+        this.connection = connection;
+    }
+
+    public boolean canCollectDiagnosticData()throws Exception {
+        String flags = getVmFlags();
+        return flags.contains("+UnlockDiagnosticVMOptions");
+    }
+
+    public String getVmFlags() throws Exception {
+        return invoke("vmFlags");
+    }
+
+    public String getGCStats() throws Exception {
+        return invoke("gcClassStats",
+                      new String[][] {
+                              {
+                                  "InstBytes,InstCount,KlassBytes,CpAll,"    +
+                                  "annotations,MethodCount,MethodAll,ROAll," +
+                                  "RWAll,ClassName,Bytecodes,ClassLoader,Total"
+                              }
+
+                      });
+    }
+
+    String invoke(String operation, String [][] params) throws Exception {
+
+        return (String) connection.get().invoke(new ObjectName("com.sun.management:type=DiagnosticCommand"),
+                                                operation, params,
+                                                new String[] { String[].class.getName() });
+    }
+
+    String invoke(String operation) throws Exception {
+        return invoke(operation, new String[][] { null });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/jcmd-stats-collector/agent/src/test/java/com/redhat/thermostat/agent/jcmd/backend/internal/JCMDBackendTest.java	Mon Oct 09 15:56:10 2017 +0200
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent.jcmd.backend.internal;
+
+import com.redhat.thermostat.commands.agent.receiver.RequestReceiver;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.osgi.framework.BundleContext;
+
+import java.util.Dictionary;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class JCMDBackendTest {
+
+    @Test
+    public void registerToCommandChannelOnlyOnBackendActivation() {
+        BundleContext context = mock(BundleContext.class);
+
+        JCMDBackend backend = new JCMDBackend();
+        // needed to pass the bundle context
+        backend._activate_(context);
+
+        ArgumentCaptor<Dictionary> captor = ArgumentCaptor.forClass(Dictionary.class);
+        when(context.registerService(eq(RequestReceiver.class),
+                                     (RequestReceiver) anyObject(),
+                                     captor.capture())).thenReturn(null);
+
+        backend.activate();
+
+        Dictionary dictionary = captor.getValue();
+        verify(context).registerService(eq(RequestReceiver.class),
+                                        (RequestReceiver) anyObject(),
+                                        eq(dictionary));
+        assertEquals("jcmd", dictionary.get("servicename"));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/jcmd-stats-collector/agent/src/test/java/com/redhat/thermostat/agent/jcmd/backend/internal/JMXReceiverTest.java	Mon Oct 09 15:56:10 2017 +0200
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent.jcmd.backend.internal;
+
+import com.redhat.thermostat.agent.jcmd.backend.internal.model.GCStatsModel;
+import com.redhat.thermostat.agent.jcmd.backend.internal.model.JCMDBinding;
+import com.redhat.thermostat.commands.model.AgentRequest;
+import com.redhat.thermostat.commands.model.WebSocketResponse;
+import com.redhat.thermostat.jvm.overview.agent.model.VmMapperService;
+import com.redhat.thermostat.lang.schema.JSONService;
+import com.redhat.thermostat.lang.schema.models.Pid;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class JMXReceiverTest {
+
+    private JMXConnectionManager connectionManager;
+    private JSONService json;
+    private NetworkHandler networkHandler;
+    private VmMapperService mapperService;
+    private AgentRequest request;
+    private JCMDBinding binding;
+
+    private Pid pid;
+
+    @Before
+    public void setup() throws Exception {
+        connectionManager = mock(JMXConnectionManager.class);
+        json = mock(JSONService.class);
+        networkHandler = mock(NetworkHandler.class);
+        mapperService = mock(VmMapperService.class);
+        request = mock(AgentRequest.class);
+
+        when(request.getJvmId()).thenReturn("42");
+        when(request.getSystemId()).thenReturn("0x4A");
+
+        pid = new Pid(42);
+        when(mapperService.getPid("42")).thenReturn(pid);
+
+        binding = mock(JCMDBinding.class);
+        when(connectionManager.getBindings(pid)).thenReturn(binding);
+    }
+
+    @Test
+    public void testReceiverEndQueryJCMDBinding() throws Exception {
+
+        when(binding.getGCStats()).thenReturn("abcdefghilmnopqrstuvz");
+        ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
+        when(networkHandler.send(captor.capture(), eq("0x4A"), eq("42"))).
+                thenReturn(WebSocketResponse.ResponseType.OK);
+
+        ArgumentCaptor<GCStatsModel> captor2 = ArgumentCaptor.forClass(GCStatsModel.class);
+        when(json.serialiase(captor2.capture())).thenReturn("something.json");
+
+        JMXReceiver receiver = new JMXReceiver(connectionManager, json,
+                                               mapperService, networkHandler);
+        receiver.receive(request);
+        verify(binding).getGCStats();
+
+        Assert.assertEquals("something.json", captor.getValue());
+        Assert.assertEquals("abcdefghilmnopqrstuvz", captor2.getValue().getPayload());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/jcmd-stats-collector/agent/src/test/java/com/redhat/thermostat/agent/jcmd/backend/internal/model/JCMDBindingTest.java	Mon Oct 09 15:56:10 2017 +0200
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent.jcmd.backend.internal.model;
+
+import com.redhat.thermostat.agent.utils.management.MXBeanConnection;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class JCMDBindingTest {
+
+    private MXBeanConnection connection;
+    private MBeanServerConnection serverConnection;
+
+    @Before
+    public void setup() {
+        connection = mock(MXBeanConnection.class);
+        serverConnection = mock(MBeanServerConnection.class);
+        when(connection.get()).thenReturn(serverConnection);
+
+    }
+
+    @Test
+    public void testJCMDParsesJVMFlags() throws Exception {
+
+        when(serverConnection.invoke(eq(new ObjectName("com.sun.management:type=DiagnosticCommand")),
+                                     eq("vmFlags"), any(String[][].class),
+                                     any(String[].class))).
+                thenReturn("+UnlockDiagnosticVMOptions -something");
+
+        JCMDBinding binding = new JCMDBinding(connection);
+
+        assertTrue(binding.canCollectDiagnosticData());
+    }
+
+    @Test
+    public void testJCMDRetrievesAllGCClassStats() throws Exception {
+
+        ArgumentCaptor<String[][]> captor = ArgumentCaptor.forClass(String[][].class);
+
+        when(serverConnection.invoke(eq(new ObjectName("com.sun.management:type=DiagnosticCommand")),
+                                     eq("gcClassStats"), captor.capture(),
+                                     any(String[].class))).thenReturn("42");
+
+        JCMDBinding binding = new JCMDBinding(connection);
+        assertEquals("42", binding.getGCStats());
+
+        String parameters = captor.getValue()[0][0];
+        assertEquals("InstBytes,InstCount,KlassBytes,CpAll,annotations," +
+                     "MethodCount,MethodAll,ROAll,RWAll,ClassName,Bytecodes," +
+                     "ClassLoader,Total", parameters);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/jcmd-stats-collector/distribution/assemblies/plugin-assembly.xml	Mon Oct 09 15:56:10 2017 +0200
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright 2012-2017 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.
+
+-->
+<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
+  <id>plugin-assembly</id>
+  <formats>
+    <format>zip</format>
+  </formats>
+  <includeBaseDirectory>false</includeBaseDirectory>
+  
+  <dependencySets>
+    <dependencySet>
+      <includes>
+        <include>com.redhat.thermostat.agent:thermostat-jcmd-stats-collector-agent</include>
+      </includes>
+      <useProjectArtifact>false</useProjectArtifact>
+      <useStrictFiltering>true</useStrictFiltering>
+      <outputDirectory>plugins/${thermostat.plugin}</outputDirectory>
+    </dependencySet>
+  </dependencySets>
+
+  <fileSets>
+    <fileSet>
+      <includes>
+        <include>thermostat-plugin.xml</include>
+      </includes>
+      <outputDirectory>plugins/${thermostat.plugin}</outputDirectory>
+      <filtered>true</filtered>
+    </fileSet>
+    <fileSet>
+      <directory>configFiles</directory>
+      <outputDirectory>etc/plugins.d/${thermostat.plugin}</outputDirectory>
+      <filtered>true</filtered>
+    </fileSet>
+  </fileSets>
+</assembly>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/jcmd-stats-collector/distribution/configFiles/gateway.properties	Mon Oct 09 15:56:10 2017 +0200
@@ -0,0 +1,2 @@
+# URL to the microservice provided by the Thermostat web gateway
+gatewayURL=https://localhost:30000/jcmd/0.0.1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/jcmd-stats-collector/distribution/pom.xml	Mon Oct 09 15:56:10 2017 +0200
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright 2012-2017 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.agent</groupId>
+    <artifactId>thermostat-jcmd-stats-collector</artifactId>
+    <version>2.99.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>thermostat-jcmd-stats-collector-distribution</artifactId>
+  <packaging>pom</packaging>
+
+  <name>Thermostat JCMD Stats Collector Plugin distribution</name>
+  
+  <properties>
+    <thermostat.plugin>jcmd</thermostat.plugin>
+  </properties>
+
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-assembly-plugin</artifactId>
+        <configuration>
+          <descriptors>
+            <descriptor>assemblies/plugin-assembly.xml</descriptor>
+          </descriptors>
+          <appendAssemblyId>false</appendAssemblyId>
+        </configuration>
+        <executions>
+          <execution>
+            <id>assemble-plugin</id>
+            <phase>package</phase>
+            <goals>
+              <goal>single</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+  
+  <dependencies>
+    <dependency>
+      <groupId>com.redhat.thermostat.agent</groupId>
+      <artifactId>thermostat-jcmd-stats-collector-agent</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+
+</project>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/jcmd-stats-collector/distribution/thermostat-plugin.xml	Mon Oct 09 15:56:10 2017 +0200
@@ -0,0 +1,51 @@
+<?xml version="1.0"?>
+<!--
+
+ Copyright 2012-2017 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.
+
+-->
+<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">
+  <extensions>
+    <extension>
+      <name>agent</name>
+      <bundles>
+        <bundle><symbolic-name>com.redhat.thermostat.agent.jcmd</symbolic-name><version>${project.version}</version></bundle>
+      </bundles>
+    </extension>
+  </extensions>
+</plugin>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/jcmd-stats-collector/pom.xml	Mon Oct 09 15:56:10 2017 +0200
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright 2012-2017 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.agent</groupId>
+    <artifactId>thermostat-plugins</artifactId>
+    <version>2.99.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>thermostat-jcmd-stats-collector</artifactId>
+  <packaging>pom</packaging>
+
+  <name>Thermostat JCMD Stats Collector plugin</name>
+
+  <modules>
+    <module>agent</module>
+    <module>distribution</module>
+  </modules>
+
+</project>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/jvm-overview/pom.xml.orig	Mon Oct 09 15:56:10 2017 +0200
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright 2012-2017 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-plugins</artifactId>
+    <version>1.99.12-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>thermostat-host-overview</artifactId>
+  <packaging>pom</packaging>
+
+  <name>Thermostat Host Overview plugin</name>
+
+  <modules>
+    <module>agent</module>
+    <module>distribution</module>
+  </modules>
+
+</project>
+
--- a/plugins/pom.xml	Fri Oct 06 14:14:13 2017 -0400
+++ b/plugins/pom.xml	Mon Oct 09 15:56:10 2017 +0200
@@ -64,6 +64,7 @@
     <module>commands</module>
     <module>vm-byteman</module>
     <module>vm-compiler</module>
+    <module>jcmd-stats-collector</module>
     <!--<module>vm-cpu</module>-->
     <!--<module>vm-classstat</module>-->
     <!--<module>vm-heap-analysis</module>-->