# HG changeset patch # User Omair Majid # Date 1368811367 14400 # Node ID 0d23a5a62b1a9e5435b9fa388dcdad2b9d4abe71 # Parent cc4b35354a3925a9b3527f6e5ec21835af71019f Record and display JMX notifications for VMs Reviewed-by: neugens Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2013-May/006563.html diff -r cc4b35354a39 -r 0d23a5a62b1a agent/core/src/main/java/com/redhat/thermostat/utils/management/MXBeanConnection.java --- a/agent/core/src/main/java/com/redhat/thermostat/utils/management/MXBeanConnection.java Thu May 16 16:39:00 2013 +0200 +++ b/agent/core/src/main/java/com/redhat/thermostat/utils/management/MXBeanConnection.java Fri May 17 13:22:47 2013 -0400 @@ -36,10 +36,13 @@ package com.redhat.thermostat.utils.management; +import javax.management.MBeanServerConnection; import javax.management.MalformedObjectNameException; public interface MXBeanConnection { E createProxy(String name, Class proxyClass) throws MalformedObjectNameException; + MBeanServerConnection get(); + } diff -r cc4b35354a39 -r 0d23a5a62b1a agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/MXBeanConnectionImpl.java --- a/agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/MXBeanConnectionImpl.java Thu May 16 16:39:00 2013 +0200 +++ b/agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/MXBeanConnectionImpl.java Fri May 17 13:22:47 2013 -0400 @@ -61,6 +61,11 @@ return JMX.newMXBeanProxy(mbsc, objectName, proxyClass); } + @Override + public MBeanServerConnection get() { + return mbsc; + } + void close() throws IOException { connection.close(); } diff -r cc4b35354a39 -r 0d23a5a62b1a client/swing/src/main/java/com/redhat/thermostat/client/swing/IconResource.java --- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/IconResource.java Thu May 16 16:39:00 2013 +0200 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/IconResource.java Fri May 17 13:22:47 2013 -0400 @@ -68,6 +68,8 @@ public static final IconResource SEARCH = new IconResource(ICON_PREFIX + "16x16/actions/search.png"); + public static final IconResource RECORD = new IconResource(ICON_PREFIX + "16x16/actions/media-record.png"); + private final String path; private IconResource(String descriptor) { diff -r cc4b35354a39 -r 0d23a5a62b1a distribution/assembly/all-plugin-assembly.xml --- a/distribution/assembly/all-plugin-assembly.xml Thu May 16 16:39:00 2013 +0200 +++ b/distribution/assembly/all-plugin-assembly.xml Fri May 17 13:22:47 2013 -0400 @@ -58,6 +58,7 @@ com.redhat.thermostat:thermostat-vm-cpu-distribution com.redhat.thermostat:thermostat-vm-gc-distribution com.redhat.thermostat:thermostat-vm-heap-analysis-distribution + com.redhat.thermostat:thermostat-vm-jmx-distribution com.redhat.thermostat:thermostat-vm-memory-distribution com.redhat.thermostat:thermostat-vm-overview-distribution diff -r cc4b35354a39 -r 0d23a5a62b1a distribution/pom.xml --- a/distribution/pom.xml Thu May 16 16:39:00 2013 +0200 +++ b/distribution/pom.xml Fri May 17 13:22:47 2013 -0400 @@ -513,6 +513,12 @@ com.redhat.thermostat + thermostat-vm-jmx-distribution + ${project.version} + zip + + + com.redhat.thermostat thermostat-vm-memory-distribution ${project.version} zip diff -r cc4b35354a39 -r 0d23a5a62b1a pom.xml --- a/pom.xml Thu May 16 16:39:00 2013 +0200 +++ b/pom.xml Fri May 17 13:22:47 2013 -0400 @@ -147,6 +147,7 @@ vm-classstat vm-memory vm-heap-analysis + vm-jmx numa integration-tests diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/agent/pom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/agent/pom.xml Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,82 @@ + + + 4.0.0 + + thermostat-vm-jmx + com.redhat.thermostat + 0.8.0-SNAPSHOT + + thermostat-vm-jmx-agent + bundle + Thermostat VM JMX Agent plugin + + + + org.apache.felix + maven-bundle-plugin + true + + + Red Hat, Inc. + com.redhat.thermostat.vm.jmx.agent + com.redhat.thermostat.vm.jmx.agent.internal.Activator + + + com.redhat.thermostat.vm.jmx.agent.internal + + + <_nouses>true + + + + + + + + junit + junit + test + + + org.mockito + mockito-core + test + + + com.redhat.thermostat + thermostat-common-test + ${project.version} + test + + + org.osgi + org.osgi.core + provided + + + org.osgi + org.osgi.compendium + provided + + + com.redhat.thermostat + thermostat-common-core + ${project.version} + + + com.redhat.thermostat + thermostat-agent-core + ${project.version} + + + com.redhat.thermostat + thermostat-agent-command + ${project.version} + + + com.redhat.thermostat + thermostat-vm-jmx-common + ${project.version} + + + diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/agent/src/main/java/com/redhat/thermostat/vm/jmx/agent/internal/Activator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/agent/src/main/java/com/redhat/thermostat/vm/jmx/agent/internal/Activator.java Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,100 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.jmx.agent.internal; + +import java.util.Map; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; + +import com.redhat.thermostat.agent.command.ReceiverRegistry; +import com.redhat.thermostat.backend.Backend; +import com.redhat.thermostat.common.MultipleServiceTracker; +import com.redhat.thermostat.common.Version; +import com.redhat.thermostat.utils.management.MXBeanConnectionPool; +import com.redhat.thermostat.vm.jmx.common.JmxNotificationDAO; + +public class Activator implements BundleActivator { + + private ServiceRegistration registration; + private JmxBackend jmxBackend; + private MultipleServiceTracker tracker; + + @Override + public void start(final BundleContext context) throws Exception { + + Class[] deps = new Class[] { JmxNotificationDAO.class, MXBeanConnectionPool.class }; + tracker = new MultipleServiceTracker(context, deps, new MultipleServiceTracker.Action() { + + @Override + public void dependenciesAvailable(Map services) { + MXBeanConnectionPool pool = (MXBeanConnectionPool) services.get(MXBeanConnectionPool.class.getName()); + JmxNotificationDAO dao = (JmxNotificationDAO) services.get(JmxNotificationDAO.class.getName()); + Version version = new Version(context.getBundle()); + ReceiverRegistry registry = new ReceiverRegistry(context); + JmxRequestListener receiver = new JmxRequestListener(); + jmxBackend = new JmxBackend(version, registry, dao, pool, receiver); + receiver.setBackend(jmxBackend); + registration = context.registerService(Backend.class, jmxBackend, null); + } + + @Override + public void dependenciesUnavailable() { + registration.unregister(); + registration = null; + if (jmxBackend.isActive()) { + jmxBackend.deactivate(); + } + } + }); + + tracker.open(); + + } + + /** For testing only */ + JmxBackend getBackend() { + return jmxBackend; + } + + @Override + public void stop(BundleContext context) throws Exception { + tracker.close(); + } + +} diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/agent/src/main/java/com/redhat/thermostat/vm/jmx/agent/internal/JmxBackend.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/agent/src/main/java/com/redhat/thermostat/vm/jmx/agent/internal/JmxBackend.java Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,209 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.jmx.agent.internal; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.management.InstanceNotFoundException; +import javax.management.IntrospectionException; +import javax.management.MBeanServerConnection; +import javax.management.MBeanServerDelegate; +import javax.management.MBeanServerNotification; +import javax.management.Notification; +import javax.management.NotificationListener; +import javax.management.ObjectName; +import javax.management.ReflectionException; + +import com.redhat.thermostat.agent.command.ReceiverRegistry; +import com.redhat.thermostat.agent.command.RequestReceiver; +import com.redhat.thermostat.backend.BaseBackend; +import com.redhat.thermostat.common.Version; +import com.redhat.thermostat.common.utils.LoggingUtils; +import com.redhat.thermostat.utils.management.MXBeanConnection; +import com.redhat.thermostat.utils.management.MXBeanConnectionPool; +import com.redhat.thermostat.vm.jmx.common.JmxNotification; +import com.redhat.thermostat.vm.jmx.common.JmxNotificationDAO; + +public class JmxBackend extends BaseBackend { + + private static final Logger logger = LoggingUtils.getLogger(JmxBackend.class); + + private final ReceiverRegistry registry; + private final RequestReceiver receiver; + private final JmxNotificationDAO dao; + private final MXBeanConnectionPool pool; + + private final NotificationListener registrationNotificationListener; + private final NotificationListener notificationWriter; + + private final Map connections = new HashMap<>(); + + private boolean isActive = false; + + public JmxBackend(Version version, ReceiverRegistry registry, JmxNotificationDAO dao, MXBeanConnectionPool pool, RequestReceiver receiver) { + super("VM JMX Backend", "gathers JMX information using JMX", "Red Hat, Inc.", version.getVersionNumber()); + + this.registry = registry; + this.pool = pool; + this.dao = dao; + + this.registrationNotificationListener = new RegistrationNotificationListener(); + this.notificationWriter = new NotificationWriter(); + + this.receiver = receiver; + } + + @Override + public int getOrderValue() { + return ORDER_USER_GROUP + 99; + } + + @Override + public boolean activate() { + if (isActive) { + return true; + } + + registry.registerReceiver(receiver); + + isActive = true; + return isActive; + } + + @Override + public boolean deactivate() { + if (!isActive) { + return true; + } + + registry.unregisterReceivers(); + + isActive = false; + return true; + } + + @Override + public boolean isActive() { + return isActive; + } + + public void enableNotificationsFor(String vmId) { + int pid = Integer.valueOf(vmId); + try { + MXBeanConnection connection = pool.acquire(pid); + connections.put(pid, connection); + MBeanServerConnection server = connection.get(); + Set names = server.queryNames(null, null); + for (ObjectName name : names) { + if (name.equals(MBeanServerDelegate.DELEGATE_NAME)) { + server.addNotificationListener(MBeanServerDelegate.DELEGATE_NAME, this.registrationNotificationListener, null, pid); + } else { + addNotificationListenerToMBean(pid, server, name); + } + } + } catch (Exception e) { + logger.log(Level.WARNING, "Unable to connect to the mx bean connector", e); + } + } + + public void disableNotificationsFor(String vmId) { + int pid = Integer.valueOf(vmId); + + MXBeanConnection connection = connections.get(pid); + try { + pool.release(pid, connection); + } catch (Exception e) { + logger.warning("Unable to release mx bean connection"); + } + } + + private class RegistrationNotificationListener implements NotificationListener { + + @Override + public void handleNotification(Notification notification, Object handback) { + Integer pid = (Integer) handback; + MBeanServerConnection server = connections.get(pid).get(); + MBeanServerNotification serverNotification = (MBeanServerNotification) notification; + ObjectName name = serverNotification.getMBeanName(); + + try { + if (MBeanServerNotification.REGISTRATION_NOTIFICATION.equals(serverNotification.getType())) { + logger.fine("MBean Registered: " + name); + addNotificationListenerToMBean(pid, server, name); + } else if (MBeanServerNotification.UNREGISTRATION_NOTIFICATION.equals(serverNotification.getType())) { + logger.fine("MBean Unregistered: " + name); + // we should remove the listener, but the object is not + // around to emit notifications + } + } catch (IOException | InstanceNotFoundException | IntrospectionException | ReflectionException e) { + logger.log(Level.WARNING, "exception while handling MBeanServerNotification", e); + } + } + + } + + // Writes the notification to storage + private class NotificationWriter implements NotificationListener { + + @Override + public void handleNotification(Notification notification, Object handback) { + int pid = (Integer) handback; + + JmxNotification data = new JmxNotification(); + data.setVmId(pid); + data.setImportance("unknown"); + data.setTimeStamp(notification.getTimeStamp()); + data.setSourceBackend(JmxBackend.class.getName()); + data.setSourceDetails("dunno"); + data.setContents(notification.toString()); + dao.addNotification(data); + + } + } + + private void addNotificationListenerToMBean(int pid, MBeanServerConnection server, ObjectName name) + throws InstanceNotFoundException, IntrospectionException, ReflectionException, IOException { + if (server.getMBeanInfo(name).getNotifications().length > 0) { + server.addNotificationListener(name, JmxBackend.this.notificationWriter, null, pid); + } + } +} diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/agent/src/main/java/com/redhat/thermostat/vm/jmx/agent/internal/JmxRequestListener.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/agent/src/main/java/com/redhat/thermostat/vm/jmx/agent/internal/JmxRequestListener.java Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,71 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.jmx.agent.internal; + +import com.redhat.thermostat.agent.command.RequestReceiver; +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.vm.jmx.common.JmxCommand; + +public class JmxRequestListener implements RequestReceiver { + + private JmxBackend backend; + + public void setBackend(JmxBackend backend) { + this.backend = backend; + } + + @Override + public Response receive(Request request) { + Response response = new Response(ResponseType.OK); + String vmId = request.getParameter(JmxCommand.VM_ID); + String command = request.getParameter(JmxCommand.class.getName()); + + switch (JmxCommand.valueOf(command)) { + case DISABLE_JMX_NOTIFICATIONS: + backend.disableNotificationsFor(vmId); + break; + case ENABLE_JMX_NOTIFICATIONS: + backend.enableNotificationsFor(vmId); + break; + } + + return response; + } + +} diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/agent/src/test/java/com/redhat/thermostat/vm/jmx/agent/internal/ActivatorTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/agent/src/test/java/com/redhat/thermostat/vm/jmx/agent/internal/ActivatorTest.java Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,83 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.jmx.agent.internal; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.junit.Test; +import org.osgi.framework.Bundle; +import org.osgi.framework.Version; + +import com.redhat.thermostat.backend.Backend; +import com.redhat.thermostat.testutils.StubBundleContext; +import com.redhat.thermostat.utils.management.MXBeanConnectionPool; +import com.redhat.thermostat.vm.jmx.agent.internal.Activator; +import com.redhat.thermostat.vm.jmx.agent.internal.JmxBackend; +import com.redhat.thermostat.vm.jmx.common.JmxNotificationDAO; + +public class ActivatorTest { + + @Test + public void verifyActviatorRegistersBackend() throws Exception { + StubBundleContext bundleContext = new StubBundleContext(); + + Bundle bundle = mock(Bundle.class); + Version version = new Version(1, 1, 1); + when(bundle.getVersion()).thenReturn(version); + bundleContext.setBundle(bundle); + + bundleContext.registerService(JmxNotificationDAO.class, mock(JmxNotificationDAO.class), null); + bundleContext.registerService(MXBeanConnectionPool.class, mock(MXBeanConnectionPool.class), null); + + Activator activator = new Activator(); + + activator.start(bundleContext); + + assertTrue(bundleContext.isServiceRegistered(Backend.class.getName(), JmxBackend.class)); + assertEquals(3, bundleContext.getAllServices().size()); + + // thermostat will activate the backend; simulate that + activator.getBackend().activate(); + + activator.stop(bundleContext); + + assertEquals(2, bundleContext.getAllServices().size()); + } +} diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/agent/src/test/java/com/redhat/thermostat/vm/jmx/agent/internal/JmxBackendTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/agent/src/test/java/com/redhat/thermostat/vm/jmx/agent/internal/JmxBackendTest.java Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,283 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.jmx.agent.internal; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Matchers.isA; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +import java.util.HashSet; +import java.util.Set; + +import javax.management.MBeanInfo; +import javax.management.MBeanNotificationInfo; +import javax.management.MBeanServerConnection; +import javax.management.MBeanServerDelegate; +import javax.management.MBeanServerNotification; +import javax.management.Notification; +import javax.management.NotificationFilter; +import javax.management.NotificationListener; +import javax.management.ObjectName; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import com.redhat.thermostat.agent.command.ReceiverRegistry; +import com.redhat.thermostat.agent.command.RequestReceiver; +import com.redhat.thermostat.common.Ordered; +import com.redhat.thermostat.common.Version; +import com.redhat.thermostat.utils.management.MXBeanConnection; +import com.redhat.thermostat.utils.management.MXBeanConnectionPool; +import com.redhat.thermostat.vm.jmx.common.JmxNotification; +import com.redhat.thermostat.vm.jmx.common.JmxNotificationDAO; + +public class JmxBackendTest { + + private Version version; + private ReceiverRegistry registry; + private MXBeanConnectionPool pool; + private JmxNotificationDAO dao; + private JmxBackend backend; + private RequestReceiver receiver; + + @Before + public void setUp() { + version = mock(Version.class); + when(version.getVersionNumber()).thenReturn("foo"); + + registry = mock(ReceiverRegistry.class); + receiver = mock(RequestReceiver.class); + dao = mock(JmxNotificationDAO.class); + pool = mock(MXBeanConnectionPool.class); + + backend = new JmxBackend(version, registry, dao, pool, receiver); + } + + @Test + public void testOrderValue() { + assertTrue(backend.getOrderValue() > Ordered.ORDER_USER_GROUP); + } + + @Test + public void testActivation() { + assertFalse(backend.isActive()); + assertTrue(backend.activate()); + assertTrue(backend.isActive()); + assertTrue(backend.activate()); + assertTrue(backend.isActive()); + } + + @Test + public void testDeactivation() { + assertTrue(backend.activate()); + + assertTrue(backend.isActive()); + + assertTrue(backend.deactivate()); + + assertFalse(backend.isActive()); + } + + @Test + public void testDectivateTwice() { + assertTrue(backend.activate()); + assertTrue(backend.isActive()); + + assertTrue(backend.deactivate()); + assertFalse(backend.isActive()); + assertTrue(backend.deactivate()); + assertFalse(backend.isActive()); + } + + @Test + public void testNotificationsEnabled() throws Exception { + ObjectName name1 = mock(ObjectName.class); + Set names = new HashSet(); + names.add(name1); + + MBeanInfo info1 = mock(MBeanInfo.class); + when(info1.getNotifications()).thenReturn(new MBeanNotificationInfo[10]); + + MBeanServerConnection actual = mock(MBeanServerConnection.class); + when(actual.queryNames(null, null)).thenReturn(names); + when(actual.getMBeanInfo(name1)).thenReturn(info1); + + MXBeanConnection connection = mock(MXBeanConnection.class); + when(connection.get()).thenReturn(actual); + when(pool.acquire(0)).thenReturn(connection); + + backend.enableNotificationsFor("0"); + + verify(actual).addNotificationListener(eq(name1), any(NotificationListener.class), eq((NotificationFilter) null), any()); + } + + @Test + public void testJmxNotificationAddedToStorage() throws Exception { + ObjectName name1 = mock(ObjectName.class); + Set names = new HashSet(); + names.add(name1); + + MBeanInfo info1 = mock(MBeanInfo.class); + when(info1.getNotifications()).thenReturn(new MBeanNotificationInfo[10]); + + MBeanServerConnection actual = mock(MBeanServerConnection.class); + when(actual.queryNames(null, null)).thenReturn(names); + when(actual.getMBeanInfo(name1)).thenReturn(info1); + + MXBeanConnection connection = mock(MXBeanConnection.class); + when(connection.get()).thenReturn(actual); + when(pool.acquire(0)).thenReturn(connection); + + backend.enableNotificationsFor("0"); + + ArgumentCaptor listenerCaptor = ArgumentCaptor.forClass(NotificationListener.class); + ArgumentCaptor handbackCaptor = ArgumentCaptor.forClass(Object.class); + + verify(actual).addNotificationListener(eq(name1), listenerCaptor.capture(), eq((NotificationFilter) null), handbackCaptor.capture()); + + NotificationListener listener = listenerCaptor.getValue(); + + Notification notification = mock(Notification.class); + when(notification.toString()).thenReturn("testing"); + + listener.handleNotification(notification, handbackCaptor.getValue()); + + verify(dao).addNotification(isA(JmxNotification.class)); + } + + @Test + public void testMBeanRegisteredNotification() throws Exception { + ObjectName serverBean = MBeanServerDelegate.DELEGATE_NAME; + Set names = new HashSet(); + names.add(serverBean); + + MBeanInfo serverBeanInfo = mock(MBeanInfo.class); + when(serverBeanInfo.getNotifications()).thenReturn(new MBeanNotificationInfo[10]); + + ObjectName newBeanName = mock(ObjectName.class); + MBeanInfo newBeanInfo = mock(MBeanInfo.class); + when(newBeanInfo.getNotifications()).thenReturn(new MBeanNotificationInfo[1]); + + MBeanServerNotification newMBeanNotification = mock(MBeanServerNotification.class); + when(newMBeanNotification.getType()).thenReturn(MBeanServerNotification.REGISTRATION_NOTIFICATION); + when(newMBeanNotification.getMBeanName()).thenReturn(newBeanName); + + MBeanServerConnection actual = mock(MBeanServerConnection.class); + when(actual.queryNames(null, null)).thenReturn(names); + when(actual.getMBeanInfo(serverBean)).thenReturn(serverBeanInfo); + when(actual.getMBeanInfo(newBeanName)).thenReturn(newBeanInfo); + + MXBeanConnection connection = mock(MXBeanConnection.class); + when(connection.get()).thenReturn(actual); + when(pool.acquire(0)).thenReturn(connection); + + backend.enableNotificationsFor("0"); + + ArgumentCaptor listenerCaptor = ArgumentCaptor.forClass(NotificationListener.class); + ArgumentCaptor handbackCaptor = ArgumentCaptor.forClass(Object.class); + + verify(actual).addNotificationListener(eq(serverBean), listenerCaptor.capture(), eq((NotificationFilter) null), handbackCaptor.capture()); + + NotificationListener listener = listenerCaptor.getValue(); + + listener.handleNotification(newMBeanNotification, handbackCaptor.getValue()); + + verify(actual).addNotificationListener(eq(newBeanName), isA(NotificationListener.class), eq((NotificationFilter) null), eq(handbackCaptor.getValue())); + } + + @Test + public void testMBeanUnregisteredNotification() throws Exception { + ObjectName serverBean = MBeanServerDelegate.DELEGATE_NAME; + Set names = new HashSet(); + names.add(serverBean); + + MBeanInfo serverBeanInfo = mock(MBeanInfo.class); + when(serverBeanInfo.getNotifications()).thenReturn(new MBeanNotificationInfo[10]); + + MBeanServerNotification mBeanRemovedNotification = mock(MBeanServerNotification.class); + when(mBeanRemovedNotification.getType()).thenReturn(MBeanServerNotification.UNREGISTRATION_NOTIFICATION); + + MBeanServerConnection actual = mock(MBeanServerConnection.class); + when(actual.queryNames(null, null)).thenReturn(names); + when(actual.getMBeanInfo(serverBean)).thenReturn(serverBeanInfo); + + MXBeanConnection connection = mock(MXBeanConnection.class); + when(connection.get()).thenReturn(actual); + when(pool.acquire(0)).thenReturn(connection); + + backend.enableNotificationsFor("0"); + + ArgumentCaptor listenerCaptor = ArgumentCaptor.forClass(NotificationListener.class); + ArgumentCaptor handbackCaptor = ArgumentCaptor.forClass(Object.class); + + verify(actual).addNotificationListener(eq(serverBean), listenerCaptor.capture(), eq((NotificationFilter) null), handbackCaptor.capture()); + + NotificationListener listener = listenerCaptor.getValue(); + + verify(actual).queryNames(null, null); + verify(actual).addNotificationListener(eq(MBeanServerDelegate.DELEGATE_NAME), isA(NotificationListener.class), eq((NotificationFilter) null), isA(Integer.class)); + + listener.handleNotification(mBeanRemovedNotification, handbackCaptor.getValue()); + + verifyNoMoreInteractions(actual); + } + + @Test + public void testNotificationsDisabled() throws Exception { + Set names = new HashSet(); + + MBeanServerConnection actual = mock(MBeanServerConnection.class); + when(actual.queryNames(null, null)).thenReturn(names); + + MXBeanConnection connection = mock(MXBeanConnection.class); + when(connection.get()).thenReturn(actual); + when(pool.acquire(0)).thenReturn(connection); + + backend.enableNotificationsFor("0"); + + backend.disableNotificationsFor("0"); + + verify(pool).release(0, connection); + } +} diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/agent/src/test/java/com/redhat/thermostat/vm/jmx/agent/internal/JmxRequestListenerTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/agent/src/test/java/com/redhat/thermostat/vm/jmx/agent/internal/JmxRequestListenerTest.java Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,95 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.jmx.agent.internal; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import java.net.InetSocketAddress; + +import org.junit.Before; +import org.junit.Test; + +import com.redhat.thermostat.common.command.Request; +import com.redhat.thermostat.common.command.Request.RequestType; +import com.redhat.thermostat.common.command.Response.ResponseType; +import com.redhat.thermostat.common.command.Response; +import com.redhat.thermostat.vm.jmx.common.JmxCommand; + +public class JmxRequestListenerTest { + + private static final String HOST = "example.org"; + private static final int PORT = 0; + + private JmxRequestListener requestListener; + private JmxBackend backend; + + @Before + public void setUp() { + backend = mock(JmxBackend.class); + + requestListener = new JmxRequestListener(); + requestListener.setBackend(backend); + } + + @Test + public void testEnableNotifications() { + Request req = new Request(RequestType.RESPONSE_EXPECTED, new InetSocketAddress(HOST, PORT)); + req.setParameter(JmxCommand.class.getName(), JmxCommand.ENABLE_JMX_NOTIFICATIONS.name()); + req.setParameter(JmxCommand.VM_ID, "0"); + + Response result = requestListener.receive(req); + + verify(backend).enableNotificationsFor("0"); + + assertEquals(ResponseType.OK, result.getType()); + } + + @Test + public void testDisableNotifications() { + Request req = new Request(RequestType.RESPONSE_EXPECTED, new InetSocketAddress(HOST, PORT)); + req.setParameter(JmxCommand.class.getName(), JmxCommand.DISABLE_JMX_NOTIFICATIONS.name()); + req.setParameter(JmxCommand.VM_ID, "0"); + + Response result = requestListener.receive(req); + + verify(backend).disableNotificationsFor("0"); + + assertEquals(ResponseType.OK, result.getType()); + } +} diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/client-core/pom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/client-core/pom.xml Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,79 @@ + + + 4.0.0 + + thermostat-vm-jmx + com.redhat.thermostat + 0.8.0-SNAPSHOT + + thermostat-vm-jmx-client-core + bundle + Thermostat VM JMX Client plugin + + + + org.apache.felix + maven-bundle-plugin + true + + + Red Hat, Inc. + com.redhat.thermostat.vm.jmx.client.core + com.redhat.thermostat.vm.jmx.client.core.internal.Activator + + com.redhat.thermostat.vm.jmx.client.core, + + + com.redhat.thermostat.vm.jmx.client.core.internal, + + + <_nouses>true + + + + + + + + junit + junit + test + + + org.mockito + mockito-core + test + + + com.redhat.thermostat + thermostat-common-test + ${project.version} + test + + + org.osgi + org.osgi.core + provided + + + org.osgi + org.osgi.compendium + provided + + + com.redhat.thermostat + thermostat-client-command + ${project.version} + + + com.redhat.thermostat + thermostat-client-core + ${project.version} + + + com.redhat.thermostat + thermostat-vm-jmx-common + ${project.version} + + + diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/client-core/src/main/java/com/redhat/thermostat/vm/jmx/client/core/JmxNotificationsView.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/client-core/src/main/java/com/redhat/thermostat/vm/jmx/client/core/JmxNotificationsView.java Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,57 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.jmx.client.core; + +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.vm.jmx.common.JmxNotification; + +public abstract class JmxNotificationsView extends BasicView implements UIComponent { + + public enum NotificationAction { + TOGGLE_NOTIFICATIONS, + } + + public abstract void addNotificationActionListener(ActionListener listener); + public abstract void removeNotificationActionListener(ActionListener listener); + + public abstract void setNotificationsEnabled(boolean enabled); + public abstract void clearNotifications(); + public abstract void addNotification(JmxNotification data); + +} diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/client-core/src/main/java/com/redhat/thermostat/vm/jmx/client/core/JmxNotificationsViewProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/client-core/src/main/java/com/redhat/thermostat/vm/jmx/client/core/JmxNotificationsViewProvider.java Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,45 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.jmx.client.core; + +import com.redhat.thermostat.client.core.views.ViewProvider; + +public interface JmxNotificationsViewProvider extends ViewProvider { + + @Override + public JmxNotificationsView createView(); +} diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/client-core/src/main/java/com/redhat/thermostat/vm/jmx/client/core/JmxNotificationsViewService.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/client-core/src/main/java/com/redhat/thermostat/vm/jmx/client/core/JmxNotificationsViewService.java Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,46 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.jmx.client.core; + +import com.redhat.thermostat.client.core.InformationService; +import com.redhat.thermostat.storage.core.VmRef; + +public interface JmxNotificationsViewService extends InformationService { + + public static final String SERVICE_ID = "com.redhat.thermostat.vm.jmx.notifications"; + +} diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/client-core/src/main/java/com/redhat/thermostat/vm/jmx/client/core/internal/Activator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/client-core/src/main/java/com/redhat/thermostat/vm/jmx/client/core/internal/Activator.java Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,107 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.jmx.client.core.internal; + +import java.util.Dictionary; +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.client.core.InformationService; +import com.redhat.thermostat.common.ApplicationService; +import com.redhat.thermostat.common.Constants; +import com.redhat.thermostat.common.MultipleServiceTracker; +import com.redhat.thermostat.common.MultipleServiceTracker.Action; +import com.redhat.thermostat.common.TimerFactory; +import com.redhat.thermostat.storage.core.VmRef; +import com.redhat.thermostat.storage.dao.AgentInfoDAO; +import com.redhat.thermostat.vm.jmx.client.core.JmxNotificationsViewProvider; +import com.redhat.thermostat.vm.jmx.common.JmxNotificationDAO; + +public class Activator implements BundleActivator { + + private MultipleServiceTracker depsTracker; + protected ServiceRegistration registration; + + @Override + public void start(final BundleContext context) throws Exception { + + final Class[] deps = new Class[] { + AgentInfoDAO.class, + JmxNotificationDAO.class, + ApplicationService.class, + RequestQueue.class, + JmxNotificationsViewProvider.class, + }; + + depsTracker = new MultipleServiceTracker(context, deps, new Action() { + @Override + public void dependenciesAvailable(Map services) { + AgentInfoDAO agentDao = (AgentInfoDAO) services.get(AgentInfoDAO.class.getName()); + JmxNotificationDAO notificationDao = (JmxNotificationDAO) services.get(JmxNotificationDAO.class.getName()); + JmxNotificationsViewProvider viewProvider = (JmxNotificationsViewProvider) services.get(JmxNotificationsViewProvider.class.getName()); + TimerFactory tf = ((ApplicationService) services.get(ApplicationService.class.getName())).getTimerFactory(); + RequestQueue queue = (RequestQueue) services.get(RequestQueue.class.getName()); + + JmxNotificationsViewServiceImpl notificationsView = new JmxNotificationsViewServiceImpl(agentDao, notificationDao, queue, tf, viewProvider); + + Dictionary props = new Hashtable(); + props.put(Constants.GENERIC_SERVICE_CLASSNAME, VmRef.class.getName()); + + registration = context.registerService(InformationService.class, notificationsView, props); + } + + @Override + public void dependenciesUnavailable() { + registration.unregister(); + } + + }); + depsTracker.open(); + } + + @Override + public void stop(BundleContext context) throws Exception { + + depsTracker.close(); + } + +} diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/client-core/src/main/java/com/redhat/thermostat/vm/jmx/client/core/internal/JmxNotificationsViewController.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/client-core/src/main/java/com/redhat/thermostat/vm/jmx/client/core/internal/JmxNotificationsViewController.java Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,160 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.jmx.client.core.internal; + +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +import com.redhat.thermostat.client.command.RequestQueue; +import com.redhat.thermostat.client.core.controllers.InformationServiceController; +import com.redhat.thermostat.client.core.views.BasicView; +import com.redhat.thermostat.client.core.views.BasicView.Action; +import com.redhat.thermostat.client.core.views.UIComponent; +import com.redhat.thermostat.common.ActionEvent; +import com.redhat.thermostat.common.ActionListener; +import com.redhat.thermostat.common.Timer; +import com.redhat.thermostat.common.TimerFactory; +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.command.Response.ResponseType; +import com.redhat.thermostat.storage.core.VmRef; +import com.redhat.thermostat.storage.dao.AgentInfoDAO; +import com.redhat.thermostat.vm.jmx.client.core.JmxNotificationsView; +import com.redhat.thermostat.vm.jmx.client.core.JmxNotificationsViewProvider; +import com.redhat.thermostat.vm.jmx.client.core.JmxNotificationsView.NotificationAction; +import com.redhat.thermostat.vm.jmx.common.JmxNotificationDAO; +import com.redhat.thermostat.vm.jmx.common.JmxNotification; + +public class JmxNotificationsViewController implements InformationServiceController { + + private final JmxNotificationsView view; + private final Timer timer; + private final JmxNotificationDAO dao; + private final AgentInfoDAO agentDAO; + private final VmRef vm; + + private final AtomicBoolean toEnable = new AtomicBoolean(true);; + + public JmxNotificationsViewController(AgentInfoDAO agent, JmxNotificationDAO notification, + TimerFactory timerFactory, final RequestQueue queue, + JmxNotificationsViewProvider viewProvider, + VmRef vmId) { + this.dao = notification; + this.agentDAO = agent; + this.view = viewProvider.createView(); + this.timer = timerFactory.createTimer(); + this.vm = vmId; + + initializeTimer(); + + view.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent actionEvent) { + switch (actionEvent.getActionId()) { + case HIDDEN: + stopUpdatingView(); + break; + case VISIBLE: + startUpdatingView(); + break; + } + } + }); + + view.addNotificationActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + if (actionEvent.getActionId() == NotificationAction.TOGGLE_NOTIFICATIONS) { + new JmxToggleNotificationRequest(queue).sendEnableNotificationsRequestToAgent(vm, agentDAO, toEnable.get(), + new RequestResponseListener() { + @Override + public void fireComplete(Request request, Response response) { + if (response.getType() == ResponseType.OK) { + view.setNotificationsEnabled(toEnable.get()); + toEnable.set(!toEnable.get()); + } + } + }); + } + } + }); + + } + + private void initializeTimer() { + timer.setTimeUnit(TimeUnit.SECONDS); + timer.setInitialDelay(0); + timer.setDelay(5); + timer.setSchedulingType(Timer.SchedulingType.FIXED_RATE); + timer.setAction(new Runnable() { + + private long lastTimeStamp = Long.MIN_VALUE; + + @Override + public void run() { + List notifications = dao.getNotifications(vm, lastTimeStamp); + for (JmxNotification notification : notifications) { + lastTimeStamp = Math.max(lastTimeStamp, notification.getTimeStamp()); + view.addNotification(notification); + } + } + }); + + } + + private void startUpdatingView() { + timer.start(); + } + + private void stopUpdatingView() { + timer.stop(); + } + + @Override + public UIComponent getView() { + return view; + } + + @Override + public String getLocalizedName() { + return "Notifications"; + } + +} diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/client-core/src/main/java/com/redhat/thermostat/vm/jmx/client/core/internal/JmxNotificationsViewServiceImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/client-core/src/main/java/com/redhat/thermostat/vm/jmx/client/core/internal/JmxNotificationsViewServiceImpl.java Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,84 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.jmx.client.core.internal; + +import com.redhat.thermostat.client.command.RequestQueue; +import com.redhat.thermostat.client.core.Filter; +import com.redhat.thermostat.client.core.NameMatchingRefFilter; +import com.redhat.thermostat.client.core.controllers.InformationServiceController; +import com.redhat.thermostat.common.Ordered; +import com.redhat.thermostat.common.TimerFactory; +import com.redhat.thermostat.storage.core.VmRef; +import com.redhat.thermostat.storage.dao.AgentInfoDAO; +import com.redhat.thermostat.vm.jmx.client.core.JmxNotificationsViewProvider; +import com.redhat.thermostat.vm.jmx.client.core.JmxNotificationsViewService; +import com.redhat.thermostat.vm.jmx.common.JmxNotificationDAO; + +public class JmxNotificationsViewServiceImpl implements JmxNotificationsViewService { + + private final Filter FILTER = new NameMatchingRefFilter<>(); + + private final JmxNotificationsViewProvider viewProvider; + private final JmxNotificationDAO notificationDao; + private final AgentInfoDAO agentDao; + private final RequestQueue requestQueue; + private final TimerFactory timerFactory; + + public JmxNotificationsViewServiceImpl(AgentInfoDAO agentDao, JmxNotificationDAO notificationDao, + RequestQueue requestQueue, TimerFactory timerFactory, JmxNotificationsViewProvider viewProvider) { + this.agentDao = agentDao; + this.notificationDao = notificationDao; + this.timerFactory = timerFactory; + this.requestQueue = requestQueue; + this.viewProvider = viewProvider; + } + + @Override + public Filter getFilter() { + return FILTER; + } + + @Override + public InformationServiceController getInformationServiceController(VmRef ref) { + return new JmxNotificationsViewController(agentDao, notificationDao, timerFactory, requestQueue, viewProvider, ref); + } + + @Override + public int getOrderValue() { + return Ordered.ORDER_USER_GROUP + 101; + } +} diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/client-core/src/main/java/com/redhat/thermostat/vm/jmx/client/core/internal/JmxToggleNotificationRequest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/client-core/src/main/java/com/redhat/thermostat/vm/jmx/client/core/internal/JmxToggleNotificationRequest.java Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,82 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.jmx.client.core.internal; + +import java.net.InetSocketAddress; + +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.common.command.Request.RequestType; +import com.redhat.thermostat.storage.core.HostRef; +import com.redhat.thermostat.storage.core.VmRef; +import com.redhat.thermostat.storage.dao.AgentInfoDAO; +import com.redhat.thermostat.vm.jmx.common.JmxCommand; + +public class JmxToggleNotificationRequest { + + private RequestQueue queue; + + public JmxToggleNotificationRequest(RequestQueue queue) { + this.queue = queue; + } + + public void sendEnableNotificationsRequestToAgent(VmRef vm, AgentInfoDAO agentDAO, boolean enable, RequestResponseListener responseListener) { + + HostRef targetHostRef = vm.getAgent(); + + String address = agentDAO.getAgentInformation(targetHostRef).getConfigListenAddress(); + String[] host = address.split(":"); + + InetSocketAddress target = new InetSocketAddress(host[0], Integer.parseInt(host[1])); + Request gcRequest = createRequest(target); + + gcRequest.setReceiver(JmxCommand.RECEIVER); + + gcRequest.setParameter(JmxCommand.class.getName(), enable ? JmxCommand.ENABLE_JMX_NOTIFICATIONS.name() : JmxCommand.DISABLE_JMX_NOTIFICATIONS.name()); + gcRequest.setParameter(JmxCommand.VM_ID, vm.getIdString()); + + gcRequest.addListener(responseListener); + + queue.putRequest(gcRequest); + } + + // for testing + Request createRequest(InetSocketAddress target) { + return new Request(RequestType.RESPONSE_EXPECTED, target); + } +} diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/client-core/src/test/java/com/redhat/thermostat/vm/jmx/client/core/internal/ActivatorTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/client-core/src/test/java/com/redhat/thermostat/vm/jmx/client/core/internal/ActivatorTest.java Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,76 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.jmx.client.core.internal; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; + +import org.junit.Test; + +import com.redhat.thermostat.client.command.RequestQueue; +import com.redhat.thermostat.client.core.InformationService; +import com.redhat.thermostat.common.ApplicationService; +import com.redhat.thermostat.storage.dao.AgentInfoDAO; +import com.redhat.thermostat.testutils.StubBundleContext; +import com.redhat.thermostat.vm.jmx.client.core.JmxNotificationsViewProvider; +import com.redhat.thermostat.vm.jmx.common.JmxNotificationDAO; + +public class ActivatorTest { + + @Test + public void testActivatorRegistersService() throws Exception { + StubBundleContext bundleContext = new StubBundleContext(); + + bundleContext.registerService(AgentInfoDAO.class, mock(AgentInfoDAO.class), null); + bundleContext.registerService(JmxNotificationDAO.class, mock(JmxNotificationDAO.class), null); + bundleContext.registerService(ApplicationService.class, mock(ApplicationService.class), null); + bundleContext.registerService(RequestQueue.class, mock(RequestQueue.class), null); + bundleContext.registerService(JmxNotificationsViewProvider.class, mock(JmxNotificationsViewProvider.class), null); + + Activator activator = new Activator(); + + activator.start(bundleContext); + + assertTrue(bundleContext.isServiceRegistered(InformationService.class.getName(), JmxNotificationsViewServiceImpl.class)); + + activator.stop(bundleContext); + + assertFalse(bundleContext.isServiceRegistered(InformationService.class.getName(), JmxNotificationsViewServiceImpl.class)); + + } +} diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/client-core/src/test/java/com/redhat/thermostat/vm/jmx/client/core/internal/JmxNotificationsViewControllerTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/client-core/src/test/java/com/redhat/thermostat/vm/jmx/client/core/internal/JmxNotificationsViewControllerTest.java Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,182 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.jmx.client.core.internal; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.net.InetSocketAddress; +import java.util.Arrays; +import java.util.concurrent.TimeUnit; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import com.redhat.thermostat.client.command.RequestQueue; +import com.redhat.thermostat.client.core.views.BasicView.Action; +import com.redhat.thermostat.common.ActionEvent; +import com.redhat.thermostat.common.ActionListener; +import com.redhat.thermostat.common.Timer; +import com.redhat.thermostat.common.Timer.SchedulingType; +import com.redhat.thermostat.common.TimerFactory; +import com.redhat.thermostat.common.command.Request; +import com.redhat.thermostat.storage.core.HostRef; +import com.redhat.thermostat.storage.core.VmRef; +import com.redhat.thermostat.storage.dao.AgentInfoDAO; +import com.redhat.thermostat.storage.model.AgentInformation; +import com.redhat.thermostat.vm.jmx.client.core.JmxNotificationsView; +import com.redhat.thermostat.vm.jmx.client.core.JmxNotificationsView.NotificationAction; +import com.redhat.thermostat.vm.jmx.client.core.JmxNotificationsViewProvider; +import com.redhat.thermostat.vm.jmx.common.JmxNotification; +import com.redhat.thermostat.vm.jmx.common.JmxNotificationDAO; + +public class JmxNotificationsViewControllerTest { + + private AgentInfoDAO agentDao; + private JmxNotificationDAO notificationDao; + private JmxNotificationsView view; + private JmxNotificationsViewProvider viewProvider; + private Timer timer; + private TimerFactory timerFactory; + private VmRef vm; + private RequestQueue queue; + private JmxNotificationsViewController controller; + private HostRef host; + + @Before + public void setUp() { + agentDao = mock(AgentInfoDAO.class); + notificationDao = mock(JmxNotificationDAO.class); + queue = mock(RequestQueue.class); + view = mock(JmxNotificationsView.class); + viewProvider = mock(JmxNotificationsViewProvider.class); + when(viewProvider.createView()).thenReturn(view); + timer = mock(Timer.class); + timerFactory = mock(TimerFactory.class); + when(timerFactory.createTimer()).thenReturn(timer); + + host = mock(HostRef.class); + vm = mock(VmRef.class); + when(vm.getAgent()).thenReturn(host); + + controller = new JmxNotificationsViewController(agentDao, notificationDao, timerFactory, queue, viewProvider, vm); + } + + @Test + public void verifyGetView() { + assertEquals(view, controller.getView()); + } + + @Test + public void verifyGetLocalizedName() { + assertEquals("Notifications", controller.getLocalizedName()); + } + + @Test + public void verifyTimerIsInitialized() { + verify(timer).setTimeUnit(TimeUnit.SECONDS); + verify(timer).setInitialDelay(0); + verify(timer).setDelay(5); + verify(timer).setSchedulingType(SchedulingType.FIXED_RATE); + verify(timer).setTimeUnit(TimeUnit.SECONDS); + + ArgumentCaptor actionCaptor = ArgumentCaptor.forClass(Runnable.class); + verify(timer).setAction(actionCaptor.capture()); + + Runnable timerAction = actionCaptor.getValue(); + + JmxNotification data = mock(JmxNotification.class); + when(notificationDao.getNotifications(vm, Long.MIN_VALUE)).thenReturn(Arrays.asList(data)); + + timerAction.run(); + + verify(view).addNotification(data); + + } + + @Test + public void verifyTimerIsStartedWhenViewIsVisible() { + + ArgumentCaptor listenerCaptor = ArgumentCaptor.forClass(ActionListener.class); + + verify(view).addActionListener(listenerCaptor.capture()); + + ActionListener listener = listenerCaptor.getValue(); + listener.actionPerformed(new ActionEvent>(view, Action.VISIBLE)); + + verify(timer).start(); + } + + @Test + public void verifyTimerIsStoppedWhenViewisInvisible() { + ArgumentCaptor listenerCaptor = ArgumentCaptor.forClass(ActionListener.class); + + verify(view).addActionListener(listenerCaptor.capture()); + + ActionListener listener = listenerCaptor.getValue(); + listener.actionPerformed(new ActionEvent>(view, Action.VISIBLE)); + + verify(timer).start(); + + listener.actionPerformed(new ActionEvent>(view, Action.HIDDEN)); + + verify(timer).stop(); + + } + + @Test + public void enableNotificationsWhenViewFiresEvent() { + ArgumentCaptor listenerCaptor = ArgumentCaptor.forClass(ActionListener.class); + + verify(view).addNotificationActionListener(listenerCaptor.capture()); + + AgentInformation agentInfo = mock(AgentInformation.class); + when(agentInfo.getConfigListenAddress()).thenReturn("example.com:0"); + when(agentDao.getAgentInformation(host)).thenReturn(agentInfo); + + listenerCaptor.getValue().actionPerformed(new ActionEvent<>(view, NotificationAction.TOGGLE_NOTIFICATIONS)); + + ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(Request.class); + verify(queue).putRequest(requestCaptor.capture()); + + Request req = requestCaptor.getValue(); + assertEquals(new InetSocketAddress("example.com", 0), req.getTarget()); + } +} diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/client-core/src/test/java/com/redhat/thermostat/vm/jmx/client/core/internal/JmxNotificationsViewServiceImplTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/client-core/src/test/java/com/redhat/thermostat/vm/jmx/client/core/internal/JmxNotificationsViewServiceImplTest.java Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,101 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.jmx.client.core.internal; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.junit.Before; +import org.junit.Test; + +import com.redhat.thermostat.client.command.RequestQueue; +import com.redhat.thermostat.common.Ordered; +import com.redhat.thermostat.common.Timer; +import com.redhat.thermostat.common.TimerFactory; +import com.redhat.thermostat.storage.core.VmRef; +import com.redhat.thermostat.storage.dao.AgentInfoDAO; +import com.redhat.thermostat.vm.jmx.client.core.JmxNotificationsView; +import com.redhat.thermostat.vm.jmx.client.core.JmxNotificationsViewProvider; +import com.redhat.thermostat.vm.jmx.common.JmxNotificationDAO; + +public class JmxNotificationsViewServiceImplTest { + + private AgentInfoDAO agentDao; + private JmxNotificationDAO notificationDao; + private Timer timer; + private TimerFactory timerFactory; + private JmxNotificationsViewProvider viewProvider; + private JmxNotificationsViewServiceImpl service; + private JmxNotificationsView view; + private RequestQueue queue; + + @Before + public void setUp() { + agentDao = mock(AgentInfoDAO.class); + notificationDao = mock(JmxNotificationDAO.class); + timer = mock(Timer.class); + timerFactory = mock(TimerFactory.class); + when(timerFactory.createTimer()).thenReturn(timer); + + queue = mock(RequestQueue.class); + + view = mock(JmxNotificationsView.class); + viewProvider = mock(JmxNotificationsViewProvider.class); + when(viewProvider.createView()).thenReturn(view); + + service = new JmxNotificationsViewServiceImpl(agentDao, notificationDao, queue, timerFactory, viewProvider); + } + + @Test + public void verifyGetFilter() { + assertNotNull(service.getFilter()); + } + + @Test + public void verifyGetInformationServiceController() { + VmRef vm = mock(VmRef.class); + assertNotNull(service.getInformationServiceController(vm)); + } + + @Test + public void verifyGetOrderValue() { + assertTrue(service.getOrderValue() > Ordered.ORDER_USER_GROUP); + } + +} diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/client-core/src/test/java/com/redhat/thermostat/vm/jmx/client/core/internal/JmxToggleNotificationRequestTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/client-core/src/test/java/com/redhat/thermostat/vm/jmx/client/core/internal/JmxToggleNotificationRequestTest.java Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,119 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.jmx.client.core.internal; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.net.InetSocketAddress; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +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.storage.core.HostRef; +import com.redhat.thermostat.storage.core.VmRef; +import com.redhat.thermostat.storage.dao.AgentInfoDAO; +import com.redhat.thermostat.storage.model.AgentInformation; +import com.redhat.thermostat.vm.jmx.common.JmxCommand; + +public class JmxToggleNotificationRequestTest { + + private static final String HOST = "example.com"; + private static final int PORT = 0; + + private RequestQueue queue; + private ArgumentCaptor requestCaptor; + private HostRef host; + private VmRef vm; + private AgentInfoDAO agentDAO; + private RequestResponseListener responseListener; + private AgentInformation agentInfo; + + @Before + public void setUp() { + queue = mock(RequestQueue.class); + requestCaptor = ArgumentCaptor.forClass(Request.class); + + host = mock(HostRef.class); + vm = mock(VmRef.class); + when(vm.getAgent()).thenReturn(host); + + agentDAO = mock(AgentInfoDAO.class); + + agentInfo = mock(AgentInformation.class); + when(agentInfo.getConfigListenAddress()).thenReturn(HOST + ":" + PORT); + when(agentDAO.getAgentInformation(host)).thenReturn(agentInfo); + + responseListener = mock(RequestResponseListener.class); + } + + @Test + public void testEnableNotificationMessage() { + new JmxToggleNotificationRequest(queue).sendEnableNotificationsRequestToAgent(vm, agentDAO, true, responseListener); + + verify(queue).putRequest(requestCaptor.capture()); + + Request req = requestCaptor.getValue(); + + assertEquals(new InetSocketAddress(HOST, PORT), req.getTarget()); + assertEquals(JmxCommand.RECEIVER, req.getReceiver()); + assertEquals(vm.getIdString(), req.getParameter(JmxCommand.VM_ID)); + + assertEquals(JmxCommand.ENABLE_JMX_NOTIFICATIONS.name(), req.getParameter(JmxCommand.class.getName())); + } + + @Test + public void testDisableNotificationMessage() { + new JmxToggleNotificationRequest(queue).sendEnableNotificationsRequestToAgent(vm, agentDAO, false, responseListener); + + verify(queue).putRequest(requestCaptor.capture()); + + Request req = requestCaptor.getValue(); + + assertEquals(new InetSocketAddress(HOST, PORT), req.getTarget()); + assertEquals(JmxCommand.RECEIVER, req.getReceiver()); + assertEquals(vm.getIdString(), req.getParameter(JmxCommand.VM_ID)); + + assertEquals(JmxCommand.DISABLE_JMX_NOTIFICATIONS.name(), req.getParameter(JmxCommand.class.getName())); + } +} diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/client-swing/pom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/client-swing/pom.xml Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,87 @@ + + + 4.0.0 + + thermostat-vm-jmx + com.redhat.thermostat + 0.8.0-SNAPSHOT + + thermostat-vm-jmx-client-swing + bundle + Thermostat VM JMX Swing Client plugin + + + + org.apache.felix + maven-bundle-plugin + true + + + Red Hat, Inc. + com.redhat.thermostat.vm.jmx.client.swing + com.redhat.thermostat.vm.jmx.client.swing.internal.Activator + + + com.redhat.thermostat.vm.jmx.client.swing.internal + + + <_nouses>true + + + + + + + + junit + junit + test + + + org.mockito + mockito-core + test + + + com.redhat.thermostat + thermostat-common-test + ${project.version} + test + + + org.easytesting + fest-swing + test + + + net.java.openjdk.cacio + cacio-tta + test + + + org.osgi + org.osgi.core + provided + + + org.osgi + org.osgi.compendium + provided + + + com.redhat.thermostat + thermostat-client-swing + ${project.version} + + + com.redhat.thermostat + thermostat-vm-jmx-common + ${project.version} + + + com.redhat.thermostat + thermostat-vm-jmx-client-core + ${project.version} + + + diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/client-swing/src/main/java/com/redhat/thermostat/vm/jmx/client/swing/internal/Activator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/client-swing/src/main/java/com/redhat/thermostat/vm/jmx/client/swing/internal/Activator.java Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,59 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.jmx.client.swing.internal; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; + +import com.redhat.thermostat.vm.jmx.client.core.JmxNotificationsViewProvider; + +public class Activator implements BundleActivator { + + private ServiceRegistration viewProviderRegistration; + + @Override + public void start(BundleContext context) throws Exception { + viewProviderRegistration = context.registerService(JmxNotificationsViewProvider.class, new JmxNotificationsSwingViewProvider(), null); + } + + @Override + public void stop(BundleContext context) throws Exception { + viewProviderRegistration.unregister(); + } + +} diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/client-swing/src/main/java/com/redhat/thermostat/vm/jmx/client/swing/internal/JmxNotificationsSwingView.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/client-swing/src/main/java/com/redhat/thermostat/vm/jmx/client/swing/internal/JmxNotificationsSwingView.java Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,162 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.jmx.client.swing.internal; + +import java.awt.Component; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +import javax.swing.DefaultListModel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.SwingUtilities; + +import com.redhat.thermostat.client.swing.ComponentVisibleListener; +import com.redhat.thermostat.client.swing.IconResource; +import com.redhat.thermostat.client.swing.SwingComponent; +import com.redhat.thermostat.client.swing.components.ActionToggleButton; +import com.redhat.thermostat.client.swing.components.HeaderPanel; +import com.redhat.thermostat.common.ActionEvent; +import com.redhat.thermostat.common.ActionListener; +import com.redhat.thermostat.vm.jmx.client.core.JmxNotificationsView; +import com.redhat.thermostat.vm.jmx.common.JmxNotification; + +public class JmxNotificationsSwingView extends JmxNotificationsView implements SwingComponent { + + private List> listeners = new CopyOnWriteArrayList<>(); + + private final HeaderPanel visiblePanel; + private final DefaultListModel listModel = new DefaultListModel<>(); + + private ActionToggleButton toolbarButton; + + public JmxNotificationsSwingView() { + + JPanel contents = new JPanel(); + contents.setLayout(new GridBagLayout()); + GridBagConstraints c = new GridBagConstraints(); + c.weightx = 1; + c.weighty = 1; + c.fill = GridBagConstraints.BOTH; + c.anchor = GridBagConstraints.PAGE_START; + + JList issuesList = new JList<>(listModel); + + contents.add(new JScrollPane(issuesList), c); + + contents.addHierarchyListener(new ComponentVisibleListener() { + @Override + public void componentShown(Component component) { + notifier.fireAction(Action.VISIBLE); + } + + @Override + public void componentHidden(Component component) { + notifier.fireAction(Action.HIDDEN); + } + }); + + toolbarButton = new ActionToggleButton(IconResource.RECORD.getIcon(), ""); + toolbarButton.setName("toggleNotifications"); + toolbarButton.addActionListener(new java.awt.event.ActionListener() { + + @Override + public void actionPerformed(java.awt.event.ActionEvent e) { + fireNotificationAction(NotificationAction.TOGGLE_NOTIFICATIONS); + } + }); + + visiblePanel = new HeaderPanel("JMX Notifications"); + visiblePanel.addToolBarButton(toolbarButton); + visiblePanel.setContent(contents); + } + + @Override + public void addNotificationActionListener(ActionListener listener) { + listeners.add(listener); + } + + @Override + public void removeNotificationActionListener(ActionListener listener) { + listeners.remove(listener); + } + + private void fireNotificationAction(NotificationAction action) { + for (ActionListener listener : listeners) { + listener.actionPerformed(new ActionEvent<>(this, action)); + } + } + + @Override + public void setNotificationsEnabled(final boolean enabled) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + toolbarButton.setSelected(enabled); + } + }); + } + + @Override + public void clearNotifications() { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + listModel.clear(); + } + }); + } + + @Override + public void addNotification(final JmxNotification data) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + listModel.add(listModel.size(), data.getContents()); + } + }); + } + + @Override + public Component getUiComponent() { + return visiblePanel; + } + +} diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/client-swing/src/main/java/com/redhat/thermostat/vm/jmx/client/swing/internal/JmxNotificationsSwingViewProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/client-swing/src/main/java/com/redhat/thermostat/vm/jmx/client/swing/internal/JmxNotificationsSwingViewProvider.java Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,49 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.jmx.client.swing.internal; + +import com.redhat.thermostat.vm.jmx.client.core.JmxNotificationsView; +import com.redhat.thermostat.vm.jmx.client.core.JmxNotificationsViewProvider; + +public class JmxNotificationsSwingViewProvider implements JmxNotificationsViewProvider { + + @Override + public JmxNotificationsView createView() { + return new JmxNotificationsSwingView(); + } + +} diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/client-swing/src/test/java/com/redhat/thermostat/vm/jmx/client/swing/internal/AcitvatorTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/client-swing/src/test/java/com/redhat/thermostat/vm/jmx/client/swing/internal/AcitvatorTest.java Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,63 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.jmx.client.swing.internal; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.redhat.thermostat.testutils.StubBundleContext; +import com.redhat.thermostat.vm.jmx.client.core.JmxNotificationsViewProvider; + +public class AcitvatorTest { + + @Test + public void testActivator() throws Exception { + StubBundleContext bundleContext = new StubBundleContext(); + Activator activator = new Activator(); + + activator.start(bundleContext); + + assertTrue(bundleContext.isServiceRegistered(JmxNotificationsViewProvider.class.getName(), JmxNotificationsSwingViewProvider.class)); + + activator.stop(bundleContext); + + assertFalse(bundleContext.isServiceRegistered(JmxNotificationsViewProvider.class.getName(), JmxNotificationsSwingViewProvider.class)); + + } +} diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/client-swing/src/test/java/com/redhat/thermostat/vm/jmx/client/swing/internal/JmxNotificationSwingViewTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/client-swing/src/test/java/com/redhat/thermostat/vm/jmx/client/swing/internal/JmxNotificationSwingViewTest.java Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,41 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.jmx.client.swing.internal; + +public class JmxNotificationSwingViewTest { + // TODO implement this +} diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/client-swing/src/test/java/com/redhat/thermostat/vm/jmx/client/swing/internal/JmxNotificationsSwingViewProviderTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/client-swing/src/test/java/com/redhat/thermostat/vm/jmx/client/swing/internal/JmxNotificationsSwingViewProviderTest.java Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,49 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.jmx.client.swing.internal; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +public class JmxNotificationsSwingViewProviderTest { + + @Test + public void verifySwingViewCreation() { + assertTrue(new JmxNotificationsSwingViewProvider().createView() instanceof JmxNotificationsSwingView); + } +} diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/common/pom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/common/pom.xml Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,74 @@ + + + 4.0.0 + + thermostat-vm-jmx + com.redhat.thermostat + 0.8.0-SNAPSHOT + + thermostat-vm-jmx-common + bundle + Thermostat VM JMX common code + + + + org.apache.felix + maven-bundle-plugin + true + + + Red Hat, Inc. + com.redhat.thermostat.vm.jmx.common + com.redhat.thermostat.vm.jmx.common.internal.Activator + + com.redhat.thermostat.vm.jmx.common, + + + com.redhat.thermostat.vm.jmx.common.internal, + + + <_nouses>true + + + + + + + + junit + junit + test + + + org.mockito + mockito-core + test + + + com.redhat.thermostat + thermostat-common-test + ${project.version} + test + + + org.osgi + org.osgi.core + provided + + + org.osgi + org.osgi.compendium + provided + + + com.redhat.thermostat + thermostat-common-core + ${project.version} + + + com.redhat.thermostat + thermostat-storage-core + ${project.version} + + + diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/common/src/main/java/com/redhat/thermostat/vm/jmx/common/JmxCommand.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/common/src/main/java/com/redhat/thermostat/vm/jmx/common/JmxCommand.java Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,47 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.jmx.common; + +public enum JmxCommand { + + ENABLE_JMX_NOTIFICATIONS, + DISABLE_JMX_NOTIFICATIONS, + ; + + public static final String VM_ID = "VM_ID"; + public static final String RECEIVER = "com.redhat.thermostat.vm.jmx.agent.internal.JmxRequestListener"; +} diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/common/src/main/java/com/redhat/thermostat/vm/jmx/common/JmxNotification.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/common/src/main/java/com/redhat/thermostat/vm/jmx/common/JmxNotification.java Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,115 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.jmx.common; + +import com.redhat.thermostat.storage.core.Entity; +import com.redhat.thermostat.storage.core.Persist; +import com.redhat.thermostat.storage.model.BasePojo; +import com.redhat.thermostat.storage.model.TimeStampedPojo; + +@Entity +public class JmxNotification extends BasePojo implements TimeStampedPojo { + + private long timeStamp; + private int vmId; + private String importance; + private String sourceBackend; + private String sourceDetails; + private String contents; + + @Persist + public int getVmId() { + return vmId; + } + + @Persist + public void setVmId(int vmId) { + this.vmId = vmId; + } + + @Persist + public String getImportance() { + return importance; + } + + @Persist + public void setImportance(String importance) { + this.importance = importance; + } + + @Persist + public String getSourceBackend() { + return sourceBackend; + } + + @Persist + public void setSourceBackend(String sourceBackend) { + this.sourceBackend = sourceBackend; + } + + @Persist + public String getSourceDetails() { + return sourceDetails; + } + + @Persist + public void setSourceDetails(String sourceDetails) { + this.sourceDetails = sourceDetails; + } + + @Persist + public String getContents() { + return contents; + } + + @Persist + public void setContents(String contents) { + this.contents = contents; + } + + @Persist + @Override + public long getTimeStamp() { + return timeStamp; + } + + @Persist + public void setTimeStamp(long timeStamp) { + this.timeStamp = timeStamp; + } + +} diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/common/src/main/java/com/redhat/thermostat/vm/jmx/common/JmxNotificationDAO.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/common/src/main/java/com/redhat/thermostat/vm/jmx/common/JmxNotificationDAO.java Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,48 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.jmx.common; + +import java.util.List; + +import com.redhat.thermostat.storage.core.VmRef; + +public interface JmxNotificationDAO { + + void addNotification(JmxNotification notification); + + List getNotifications(VmRef notificationsFor, long timeStampSince); +} diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/common/src/main/java/com/redhat/thermostat/vm/jmx/common/internal/Activator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/common/src/main/java/com/redhat/thermostat/vm/jmx/common/internal/Activator.java Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,78 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.jmx.common.internal; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.ServiceRegistration; +import org.osgi.util.tracker.ServiceTracker; + +import com.redhat.thermostat.storage.core.Storage; +import com.redhat.thermostat.vm.jmx.common.JmxNotificationDAO; + +public class Activator implements BundleActivator { + + private ServiceTracker storageTracker; + private ServiceRegistration daoRegistration; + + @Override + public void start(final BundleContext context) throws Exception { + storageTracker = new ServiceTracker(context, Storage.class, null) { + @Override + public Object addingService(ServiceReference reference) { + Storage storage = (Storage) super.addingService(reference); + JmxNotificationDAOImpl dao = new JmxNotificationDAOImpl(storage); + daoRegistration = context.registerService(JmxNotificationDAO.class, dao, null); + return storage; + } + + @Override + public void removedService(ServiceReference reference, Object service) { + daoRegistration.unregister(); + super.removedService(reference, service); + } + }; + storageTracker.open(); + } + + @Override + public void stop(BundleContext context) throws Exception { + storageTracker.close(); + } + +} diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/common/src/main/java/com/redhat/thermostat/vm/jmx/common/internal/JmxNotificationDAOImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/common/src/main/java/com/redhat/thermostat/vm/jmx/common/internal/JmxNotificationDAOImpl.java Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,97 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.jmx.common.internal; + +import java.util.ArrayList; +import java.util.List; + +import com.redhat.thermostat.storage.core.Add; +import com.redhat.thermostat.storage.core.Category; +import com.redhat.thermostat.storage.core.Cursor; +import com.redhat.thermostat.storage.core.Key; +import com.redhat.thermostat.storage.core.Query; +import com.redhat.thermostat.storage.core.Query.Criteria; +import com.redhat.thermostat.storage.core.Storage; +import com.redhat.thermostat.storage.core.VmRef; +import com.redhat.thermostat.vm.jmx.common.JmxNotificationDAO; +import com.redhat.thermostat.vm.jmx.common.JmxNotification; + +public class JmxNotificationDAOImpl implements JmxNotificationDAO { + + // TODO: private static final Key IMPORTANCE = new Key<>("importance", + // false); + + private static final Key SOURCE_BACKEND = new Key<>("sourceBackend", false); + private static final Key SOURCE_DESCRPTION = new Key<>("sourceDescription", false); + private static final Key CONTENTS = new Key<>("contents", false); + + static final Category NOTIFICATIONS = + new Category<>("vm-jmx-notification", JmxNotification.class, + Key.AGENT_ID, Key.VM_ID, Key.TIMESTAMP, + SOURCE_BACKEND, SOURCE_DESCRPTION, CONTENTS); + + private Storage storage; + + public JmxNotificationDAOImpl(Storage storage) { + this.storage = storage; + storage.registerCategory(NOTIFICATIONS); + } + + @Override + public void addNotification(JmxNotification notification) { + Add add = storage.createAdd(NOTIFICATIONS); + add.setPojo(notification); + add.apply(); + } + + @Override + public List getNotifications(VmRef notificationsFor, long timeStampSince) { + Query query = storage.createQuery(NOTIFICATIONS); + query.where(Key.AGENT_ID, Criteria.EQUALS, notificationsFor.getAgent().getAgentId()); + query.where(Key.VM_ID, Criteria.EQUALS, notificationsFor.getId()); + query.where(Key.TIMESTAMP, Criteria.GREATER_THAN, timeStampSince); + + List results = new ArrayList<>(); + Cursor cursor = query.execute(); + while (cursor.hasNext()) { + results.add(cursor.next()); + } + + return results; + } + +} diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/common/src/test/java/com/redhat/thermostat/vm/jmx/common/internal/ActivatorTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/common/src/test/java/com/redhat/thermostat/vm/jmx/common/internal/ActivatorTest.java Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,69 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.jmx.common.internal; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; + +import org.junit.Test; + +import com.redhat.thermostat.storage.core.Storage; +import com.redhat.thermostat.testutils.StubBundleContext; +import com.redhat.thermostat.vm.jmx.common.JmxNotificationDAO; + +public class ActivatorTest { + + @Test + public void testActivator() throws Exception { + StubBundleContext bundleContext = new StubBundleContext(); + Storage storage = mock(Storage.class); + bundleContext.registerService(Storage.class, storage, null); + + Activator activator = new Activator(); + + assertFalse(bundleContext.isServiceRegistered(JmxNotificationDAO.class.getName(), JmxNotificationDAOImpl.class)); + + activator.start(bundleContext); + + assertTrue(bundleContext.isServiceRegistered(JmxNotificationDAO.class.getName(), JmxNotificationDAOImpl.class)); + + activator.stop(bundleContext); + + assertFalse(bundleContext.isServiceRegistered(JmxNotificationDAO.class.getName(), JmxNotificationDAOImpl.class)); + } +} diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/common/src/test/java/com/redhat/thermostat/vm/jmx/common/internal/JmxNotificationDAOImplTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/common/src/test/java/com/redhat/thermostat/vm/jmx/common/internal/JmxNotificationDAOImplTest.java Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,120 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.jmx.common.internal; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import com.redhat.thermostat.storage.core.Add; +import com.redhat.thermostat.storage.core.Cursor; +import com.redhat.thermostat.storage.core.HostRef; +import com.redhat.thermostat.storage.core.Key; +import com.redhat.thermostat.storage.core.Query; +import com.redhat.thermostat.storage.core.Query.Criteria; +import com.redhat.thermostat.storage.core.Storage; +import com.redhat.thermostat.storage.core.VmRef; +import com.redhat.thermostat.vm.jmx.common.JmxNotification; + +public class JmxNotificationDAOImplTest { + + private Storage storage; + + private JmxNotificationDAOImpl dao; + + @Before + public void setUp() { + storage = mock(Storage.class); + + dao = new JmxNotificationDAOImpl(storage); + } + + @Test + public void verfiyAddNotification() { + Add add = mock(Add.class); + when(storage.createAdd(JmxNotificationDAOImpl.NOTIFICATIONS)).thenReturn(add); + + JmxNotification data = mock(JmxNotification.class); + + dao.addNotification(data); + + verify(add).setPojo(data); + verify(add).apply(); + verifyNoMoreInteractions(add); + } + + @Test + public void testGetNotificationsForVmSince() { + final String AGENT_ID = "an-agent's-id"; + HostRef host = mock(HostRef.class); + when(host.getAgentId()).thenReturn(AGENT_ID); + + final int VM_ID = -1; + VmRef vm = mock(VmRef.class); + when(vm.getAgent()).thenReturn(host); + when(vm.getId()).thenReturn(VM_ID); + long timeStamp = 10; + + JmxNotification data = mock(JmxNotification.class); + + Query query = mock(Query.class); + when(storage.createQuery(JmxNotificationDAOImpl.NOTIFICATIONS)).thenReturn(query); + + Cursor cursor = mock(Cursor.class); + when(cursor.hasNext()).thenReturn(true).thenReturn(false); + when(cursor.next()).thenReturn(data).thenThrow(new AssertionError("not supposed to be called again")); + + when(query.execute()).thenReturn(cursor); + + List result = dao.getNotifications(vm, timeStamp); + + verify(query).where(Key.AGENT_ID, Criteria.EQUALS, AGENT_ID); + verify(query).where(Key.VM_ID, Criteria.EQUALS, VM_ID); + verify(query).where(Key.TIMESTAMP, Criteria.GREATER_THAN, timeStamp); + + assertEquals(1, result.size()); + assertSame(data, result.get(0)); + } +} diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/distribution/pom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/distribution/pom.xml Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,111 @@ + + + + 4.0.0 + + + com.redhat.thermostat + thermostat-vm-jmx + 0.8.0-SNAPSHOT + + + thermostat-vm-jmx-distribution + pom + + Thermostat VM JMX plugin distribution + + + vm-jmx + + + + + + maven-assembly-plugin + + + com.redhat.thermostat + thermostat-assembly + ${project.version} + + + + + plugin-assembly + + false + + + + assemble-plugin + package + + single + + + + + + + + + + com.redhat.thermostat + thermostat-vm-jmx-common + ${project.version} + + + com.redhat.thermostat + thermostat-vm-jmx-client-core + ${project.version} + + + com.redhat.thermostat + thermostat-vm-jmx-client-swing + ${project.version} + + + com.redhat.thermostat + thermostat-vm-jmx-agent + ${project.version} + + + + + diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/distribution/thermostat-plugin.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/distribution/thermostat-plugin.xml Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,59 @@ + + + + + + gui + + thermostat-vm-jmx-common-${project.version}.jar + thermostat-vm-jmx-client-core-${project.version}.jar + thermostat-vm-jmx-client-swing-${project.version}.jar + + + + agent + + thermostat-vm-jmx-agent-${project.version}.jar + thermostat-vm-jmx-common-${project.version}.jar + + + + diff -r cc4b35354a39 -r 0d23a5a62b1a vm-jmx/pom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-jmx/pom.xml Fri May 17 13:22:47 2013 -0400 @@ -0,0 +1,62 @@ + + + + 4.0.0 + + + com.redhat.thermostat + thermostat + 0.8.0-SNAPSHOT + + + thermostat-vm-jmx + pom + + Thermostat JMX plugin + + + agent + common + client-core + client-swing + distribution + + + +