# HG changeset patch # User Omair Majid # Date 1358806648 18000 # Node ID 4f3b798807f3e32e024e3e72072ceee9e01acabb # Parent 259c606241748808ef11da190383b887067a582b Introduce HostContextAction Reviewed-by: vanaltj Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2012-December/004957.html diff -r 259c60624174 -r 4f3b798807f3 client/core/src/main/java/com/redhat/thermostat/client/osgi/service/HostContextAction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/core/src/main/java/com/redhat/thermostat/client/osgi/service/HostContextAction.java Mon Jan 21 17:17:28 2013 -0500 @@ -0,0 +1,94 @@ +/* + * Copyright 2012 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.client.osgi.service; + +import com.redhat.thermostat.annotations.ExtensionPoint; +import com.redhat.thermostat.client.core.Filter; +import com.redhat.thermostat.common.dao.HostRef; + +/** + * {@code HostContextAction}s provide actions that are associated with hosts and + * can be invoked by users. The exact position and appearance of these + * {@code HostContextAction}s varies based on the implementation. + *

+ * Plugins can register implementations of this interface as OSGi services to + * provide additional {@code HostContextAction}s. + *

+ *

Implementation Note

+ *

+ * The following information is specific to the current release and may change + * in a future release. + *

+ * The swing client uses instances of this interface to provide menu items for + * the Host/VM tree. The menu is shown when a user right clicks a host in the + * Host/VM tree. A menu item for every {@code HostContextAction} is added, if + * the {@link Filter} matches, to this menu. Selecting a menu item invokes the + * appropriate {@code HostContextAction}. + * + * @see VMContextAction + */ +@ExtensionPoint +public interface HostContextAction extends ContextAction { + + /** + * A user-visible name for this {@code HostContextAction}. This should be + * localized. + */ + @Override + String getName(); + + /** + * A user-visible description for this {@code HostContextAction}. This + * should be localized. + */ + @Override + String getDescription(); + + /** + * Invoked when the user selects this {@code HostContextAction}. + * + * @param reference the host on which this {@code HostContextAction} was + * invoked on. + */ + void execute(HostRef reference); + + /** + * The {@link Filter} returned by this method is used to select what VMs + * this {@code HostContextAction} is applicable to. + */ + Filter getFilter(); +} diff -r 259c60624174 -r 4f3b798807f3 client/core/src/main/java/com/redhat/thermostat/client/osgi/service/VMContextAction.java --- a/client/core/src/main/java/com/redhat/thermostat/client/osgi/service/VMContextAction.java Mon Jan 21 13:48:50 2013 -0500 +++ b/client/core/src/main/java/com/redhat/thermostat/client/osgi/service/VMContextAction.java Mon Jan 21 17:17:28 2013 -0500 @@ -59,6 +59,8 @@ * tree. A menu item for every {@link VMContextAction} is added, if the * {@code Filter} matches, to this menu. Selecting a menu item invokes the * corresponding {@code VMContextAction}. + * + * @see HostContextAction */ @ExtensionPoint public interface VMContextAction extends ContextAction { @@ -78,10 +80,10 @@ public String getDescription(); /** - * Invoked when the user selects this context item + * Invoked when the user selects this {@code VMContextAction}. * - * @param reference specifies the vm that this context action was invoked - * on. + * @param reference specifies the vm that this {@code VMContextAction} was + * invoked on. */ void execute(VmRef reference); diff -r 259c60624174 -r 4f3b798807f3 client/core/src/main/java/com/redhat/thermostat/client/ui/UiFacadeFactory.java --- a/client/core/src/main/java/com/redhat/thermostat/client/ui/UiFacadeFactory.java Mon Jan 21 13:48:50 2013 -0500 +++ b/client/core/src/main/java/com/redhat/thermostat/client/ui/UiFacadeFactory.java Mon Jan 21 17:17:28 2013 -0500 @@ -40,6 +40,7 @@ import java.util.List; import com.redhat.thermostat.client.core.InformationService; +import com.redhat.thermostat.client.osgi.service.HostContextAction; import com.redhat.thermostat.client.osgi.service.VMContextAction; import com.redhat.thermostat.common.dao.HostInfoDAO; import com.redhat.thermostat.common.dao.HostRef; @@ -72,6 +73,10 @@ void removeVmInformationService(InformationService vmInfoService); + Collection getHostContextActions(); + void addHostContextAction(HostContextAction action); + void removeHostContextAction(HostContextAction action); + Collection getVMContextActions(); void addVMContextAction(VMContextAction service); diff -r 259c60624174 -r 4f3b798807f3 client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/MainView.java --- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/MainView.java Mon Jan 21 13:48:50 2013 -0500 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/MainView.java Mon Jan 21 17:17:28 2013 -0500 @@ -43,9 +43,10 @@ import com.redhat.thermostat.client.core.Filter; import com.redhat.thermostat.client.core.views.BasicView; +import com.redhat.thermostat.client.osgi.service.ContextAction; import com.redhat.thermostat.client.osgi.service.DecoratorProvider; import com.redhat.thermostat.client.osgi.service.MenuAction; -import com.redhat.thermostat.client.osgi.service.VMContextAction; +import com.redhat.thermostat.common.ActionEvent; import com.redhat.thermostat.common.ActionListener; import com.redhat.thermostat.common.HostsVMsLoader; import com.redhat.thermostat.common.dao.HostRef; @@ -64,8 +65,8 @@ SWITCH_HISTORY_MODE, SHOW_ABOUT_DIALOG, SHUTDOWN, - SHOW_VM_CONTEXT_MENU, - VM_CONTEXT_ACTION, + SHOW_HOST_VM_CONTEXT_MENU, + HOST_VM_CONTEXT_ACTION, } void addActionListener(ActionListener capture); @@ -96,11 +97,23 @@ /** * Removes a menu item to the window. Assumes the menu path is valid (has a - * non-zero length) and doesn't collide with existing menus. + * non-zero length) and the menu already exists. */ void removeMenu(MenuAction action); - void showVMContextActions(List actions, MouseEvent e); + /** + * Shows a popup context menu created from the list of supplied context + * actions. When an item in the popup menu is selected, an + * {@link ActionEvent} is fired with the id + * {@link Action#HOST_VM_CONTEXT_ACTION} and the user-selected + * {@link ContextAction} as the payload. + * + * @param actions the {@link ContextAction}s available to the user. + * Normally classes implementing sub-interfaces of {@link ContextAction} are used here. + * @param e the mouse event that triggered the context action. Used to + * position the context menu. + */ + void showContextActions(List actions, MouseEvent e); JFrame getTopFrame(); } diff -r 259c60624174 -r 4f3b798807f3 client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/MainWindow.java --- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/MainWindow.java Mon Jan 21 13:48:50 2013 -0500 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/MainWindow.java Mon Jan 21 17:17:28 2013 -0500 @@ -93,7 +93,9 @@ import com.redhat.thermostat.client.core.Filter; import com.redhat.thermostat.client.core.views.BasicView; import com.redhat.thermostat.client.locale.LocaleResources; +import com.redhat.thermostat.client.osgi.service.ContextAction; import com.redhat.thermostat.client.osgi.service.DecoratorProvider; +import com.redhat.thermostat.client.osgi.service.HostContextAction; import com.redhat.thermostat.client.osgi.service.MenuAction; import com.redhat.thermostat.client.osgi.service.VMContextAction; import com.redhat.thermostat.client.swing.EdtHelper; @@ -328,7 +330,7 @@ private ActionNotifier actionNotifier = new ActionNotifier<>(this); - private ThermostatPopupMenu vmContextMenu; + private ThermostatPopupMenu contextMenu; private StatusBar statusBar; private final DefaultMutableTreeNode publishedRoot = @@ -505,29 +507,27 @@ } private void registerContextActionListener(JTree agentVmTree2) { - vmContextMenu = new ThermostatPopupMenu(); + contextMenu = new ThermostatPopupMenu(); agentVmTree2.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { if (e.isPopupTrigger()) { Ref ref = getSelectedHostOrVm(); - if (ref instanceof VmRef) { - fireViewAction(Action.SHOW_VM_CONTEXT_MENU, e); - } + fireViewAction(Action.SHOW_HOST_VM_CONTEXT_MENU, e); } } }); } @Override - public void showVMContextActions(final List actions, final MouseEvent e) { + public void showContextActions(final List actions, final MouseEvent e) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { - vmContextMenu.removeAll(); + contextMenu.removeAll(); - for (final VMContextAction action: actions) { + for (final ContextAction action: actions) { JMenuItem contextAction = new JMenuItem(); contextAction.setText(action.getName()); contextAction.setToolTipText(action.getDescription()); @@ -535,15 +535,18 @@ contextAction.addActionListener(new java.awt.event.ActionListener() { @Override public void actionPerformed(java.awt.event.ActionEvent e) { - fireViewAction(Action.VM_CONTEXT_ACTION, action); + fireViewAction(Action.HOST_VM_CONTEXT_ACTION, action); } }); - vmContextMenu.add(contextAction); + + // the component name is for unit tests only + contextAction.setName(action.getName()); + + contextMenu.add(contextAction); } - vmContextMenu.show((Component)e.getSource(), e.getX(), e.getY()); + contextMenu.show((Component)e.getSource(), e.getX(), e.getY()); } - }); } diff -r 259c60624174 -r 4f3b798807f3 client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/MainWindowControllerImpl.java --- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/MainWindowControllerImpl.java Mon Jan 21 13:48:50 2013 -0500 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/MainWindowControllerImpl.java Mon Jan 21 17:17:28 2013 -0500 @@ -54,7 +54,9 @@ import com.redhat.thermostat.client.core.views.AgentInformationViewProvider; import com.redhat.thermostat.client.core.views.ClientConfigViewProvider; import com.redhat.thermostat.client.core.views.ClientConfigurationView; +import com.redhat.thermostat.client.osgi.service.ContextAction; import com.redhat.thermostat.client.osgi.service.DecoratorProvider; +import com.redhat.thermostat.client.osgi.service.HostContextAction; import com.redhat.thermostat.client.osgi.service.MenuAction; import com.redhat.thermostat.client.osgi.service.VMContextAction; import com.redhat.thermostat.client.swing.internal.MainView.Action; @@ -295,10 +297,10 @@ case SHOW_ABOUT_DIALOG: showAboutDialog(); break; - case SHOW_VM_CONTEXT_MENU: + case SHOW_HOST_VM_CONTEXT_MENU: showContextMenu(evt); break; - case VM_CONTEXT_ACTION: + case HOST_VM_CONTEXT_ACTION: handleVMHooks(evt); break; case SHUTDOWN: @@ -371,32 +373,49 @@ } private void showContextMenu(ActionEvent evt) { - List toShow = new ArrayList<>(); - VmRef vm = (VmRef) view.getSelectedHostOrVm(); + List toShow = new ArrayList<>(); + + Ref ref = view.getSelectedHostOrVm(); + if (ref instanceof HostRef) { + HostRef vm = (HostRef) ref; + + logger.log(Level.INFO, "registering applicable HostContextActions actions to show"); - logger.log(Level.INFO, "registering applicable VMContextActions actions to show"); + for (HostContextAction action : facadeFactory.getHostContextActions()) { + if (action.getFilter().matches(vm)) { + toShow.add(action); + } + } + } else if (ref instanceof VmRef) { + VmRef vm = (VmRef) ref; - for (VMContextAction action : facadeFactory.getVMContextActions()) { - if (action.getFilter().matches(vm)) { - toShow.add(action); + logger.log(Level.INFO, "registering applicable VMContextActions actions to show"); + + for (VMContextAction action : facadeFactory.getVMContextActions()) { + if (action.getFilter().matches(vm)) { + toShow.add(action); + } } } - view.showVMContextActions(toShow, (MouseEvent)evt.getPayload()); + view.showContextActions(toShow, (MouseEvent) evt.getPayload()); } private void handleVMHooks(ActionEvent event) { Object payload = event.getPayload(); - if (payload instanceof VMContextAction) { - try { + try { + if (payload instanceof HostContextAction) { + HostContextAction action = (HostContextAction) payload; + action.execute((HostRef) view.getSelectedHostOrVm()); + } else if (payload instanceof VMContextAction) { VMContextAction action = (VMContextAction) payload; action.execute((VmRef) view.getSelectedHostOrVm()); - } catch (Throwable error) { - logger.log(Level.SEVERE, ""); } + } catch (Throwable error) { + logger.log(Level.SEVERE, "error invocating context action", error); } } - + @Override public void showMainMainWindow() { view.showMainWindow(); diff -r 259c60624174 -r 4f3b798807f3 client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/UiFacadeFactoryImpl.java --- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/UiFacadeFactoryImpl.java Mon Jan 21 13:48:50 2013 -0500 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/UiFacadeFactoryImpl.java Mon Jan 21 17:17:28 2013 -0500 @@ -47,6 +47,7 @@ import com.redhat.thermostat.client.core.views.HostInformationViewProvider; import com.redhat.thermostat.client.core.views.SummaryViewProvider; import com.redhat.thermostat.client.core.views.VmInformationViewProvider; +import com.redhat.thermostat.client.osgi.service.HostContextAction; import com.redhat.thermostat.client.osgi.service.VMContextAction; import com.redhat.thermostat.client.ui.HostInformationController; import com.redhat.thermostat.client.ui.MainWindowController; @@ -66,7 +67,8 @@ private List> hostInformationServices = new ArrayList<>(); private List> vmInformationServices = new ArrayList<>(); - private Collection contextAction = new ArrayList<>(); + private Collection hostContextActions = new ArrayList<>(); + private Collection vmContextActions = new ArrayList<>(); private BundleContext context; private ApplicationService appSvc; @@ -136,13 +138,28 @@ } @Override + public Collection getHostContextActions() { + return hostContextActions; + } + + @Override + public void addHostContextAction(HostContextAction action) { + hostContextActions.add(action); + } + + @Override + public void removeHostContextAction(HostContextAction action) { + hostContextActions.remove(action); + } + + @Override public Collection getVMContextActions() { - return contextAction; + return vmContextActions; } @Override public void addVMContextAction(VMContextAction service) { - contextAction.add(service); + vmContextActions.add(service); } @Override diff -r 259c60624174 -r 4f3b798807f3 client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/osgi/HostContextActionServiceTracker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/osgi/HostContextActionServiceTracker.java Mon Jan 21 17:17:28 2013 -0500 @@ -0,0 +1,73 @@ +/* + * Copyright 2012 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.client.swing.internal.osgi; + +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.util.tracker.ServiceTracker; + +import com.redhat.thermostat.client.osgi.service.HostContextAction; +import com.redhat.thermostat.client.ui.UiFacadeFactory; + +@SuppressWarnings("rawtypes") +class HostContextActionServiceTracker extends ServiceTracker { + + private UiFacadeFactory uiFacadeFactory; + + private BundleContext context; + + @SuppressWarnings("unchecked") + HostContextActionServiceTracker(BundleContext context, UiFacadeFactory uiFacadeFactory) { + super(context, HostContextAction.class.getName(), null); + this.context = context; + this.uiFacadeFactory = uiFacadeFactory; + } + + @Override + public Object addingService(ServiceReference reference) { + @SuppressWarnings("unchecked") + HostContextAction service = (HostContextAction) super.addingService(reference); + uiFacadeFactory.addHostContextAction(service); + return service; + } + + @Override + public void removedService(ServiceReference reference, Object service) { + uiFacadeFactory.removeHostContextAction((HostContextAction)service); + super.removedService(reference, service); + } +} diff -r 259c60624174 -r 4f3b798807f3 client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/osgi/ThermostatActivator.java --- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/osgi/ThermostatActivator.java Mon Jan 21 13:48:50 2013 -0500 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/osgi/ThermostatActivator.java Mon Jan 21 17:17:28 2013 -0500 @@ -70,7 +70,8 @@ public class ThermostatActivator implements BundleActivator { private InformationServiceTracker infoServiceTracker; - private VMContextActionServiceTracker contextActionTracker; + private HostContextActionServiceTracker hostContextActionTracker; + private VMContextActionServiceTracker vmContextActionTracker; private CommandRegistry cmdReg; @@ -111,8 +112,12 @@ infoServiceTracker = new InformationServiceTracker(context, uiFacadeFactory); infoServiceTracker.open(); - contextActionTracker = new VMContextActionServiceTracker(context, uiFacadeFactory); - contextActionTracker.open(); + + hostContextActionTracker = new HostContextActionServiceTracker(context, uiFacadeFactory); + hostContextActionTracker.open(); + + vmContextActionTracker = new VMContextActionServiceTracker(context, uiFacadeFactory); + vmContextActionTracker.open(); cmdReg = new CommandRegistryImpl(context); Main main = new Main(keyring, uiFacadeFactory, new String[0]); @@ -129,7 +134,8 @@ @Override public void stop(BundleContext context) throws Exception { infoServiceTracker.close(); - contextActionTracker.close(); + hostContextActionTracker.close(); + vmContextActionTracker.close(); cmdReg.unregisterCommands(); } } diff -r 259c60624174 -r 4f3b798807f3 client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/MainWindowControllerImplTest.java --- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/MainWindowControllerImplTest.java Mon Jan 21 13:48:50 2013 -0500 +++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/MainWindowControllerImplTest.java Mon Jan 21 17:17:28 2013 -0500 @@ -66,7 +66,9 @@ import com.redhat.thermostat.client.core.Filter; import com.redhat.thermostat.client.core.views.BasicView; +import com.redhat.thermostat.client.osgi.service.ContextAction; import com.redhat.thermostat.client.osgi.service.DecoratorProvider; +import com.redhat.thermostat.client.osgi.service.HostContextAction; import com.redhat.thermostat.client.osgi.service.MenuAction; import com.redhat.thermostat.client.osgi.service.VMContextAction; import com.redhat.thermostat.client.ui.SummaryController; @@ -103,8 +105,9 @@ private HostInfoDAO mockHostsDAO; private VmInfoDAO mockVmsDAO; - private VMContextAction action1; - private VMContextAction action2; + private HostContextAction hostContextAction1; + private VMContextAction vmContextAction1; + private VMContextAction vmContextAction2; private HostFilterRegistry hostFilterRegistry; private VmFilterRegistry vmFilterRegistry; @@ -177,6 +180,7 @@ ArgumentCaptor grabInfoRegistry = ArgumentCaptor.forClass(ActionListener.class); doNothing().when(vmInfoRegistry).addActionListener(grabInfoRegistry.capture()); + setUpHostContextActions(); setUpVMContextActions(); controller = new MainWindowControllerImpl(appSvc, uiFacadeFactory, view, registryFactory, mockHostsDAO, mockVmsDAO); @@ -187,26 +191,38 @@ decoratorsListener = grabDecoratorsListener.getValue(); } + private void setUpHostContextActions() { + hostContextAction1 = mock(HostContextAction.class); + Filter hostFilter1 = mock(Filter.class); + when(hostFilter1.matches(isA(HostRef.class))).thenReturn(true); + + when(hostContextAction1.getName()).thenReturn("action1"); + when(hostContextAction1.getDescription()).thenReturn("action1desc"); + when(hostContextAction1.getFilter()).thenReturn(hostFilter1); + + when(uiFacadeFactory.getHostContextActions()).thenReturn(Arrays.asList(hostContextAction1)); + } + private void setUpVMContextActions() { - action1 = mock(VMContextAction.class); + vmContextAction1 = mock(VMContextAction.class); Filter action1Filter = mock(Filter.class); when(action1Filter.matches(isA(VmRef.class))).thenReturn(true); - when(action1.getName()).thenReturn("action1"); - when(action1.getDescription()).thenReturn("action1desc"); - when(action1.getFilter()).thenReturn(action1Filter); + when(vmContextAction1.getName()).thenReturn("action1"); + when(vmContextAction1.getDescription()).thenReturn("action1desc"); + when(vmContextAction1.getFilter()).thenReturn(action1Filter); - action2 = mock(VMContextAction.class); + vmContextAction2 = mock(VMContextAction.class); Filter action2Filter = mock(Filter.class); when(action2Filter.matches(isA(VmRef.class))).thenReturn(false); - when(action2.getName()).thenReturn("action2"); - when(action2.getDescription()).thenReturn("action2desc"); - when(action2.getFilter()).thenReturn(action2Filter); + when(vmContextAction2.getName()).thenReturn("action2"); + when(vmContextAction2.getDescription()).thenReturn("action2desc"); + when(vmContextAction2.getFilter()).thenReturn(action2Filter); Collection actions = new ArrayList<>(); - actions.add(action1); - actions.add(action2); + actions.add(vmContextAction1); + actions.add(vmContextAction2); when(uiFacadeFactory.getVMContextActions()).thenReturn(actions); } @@ -495,7 +511,24 @@ assertEquals(2, id); } - + + @Test + public void verifyHostActionsAreShown() { + HostRef host = mock(HostRef.class); + when(view.getSelectedHostOrVm()).thenReturn(host); + + MouseEvent uiEvent = mock(MouseEvent.class); + ActionEvent viewEvent = new ActionEvent<>(view, MainView.Action.SHOW_HOST_VM_CONTEXT_MENU); + viewEvent.setPayload(uiEvent); + + l.actionPerformed(viewEvent); + + List actions = new ArrayList<>(); + actions.add(hostContextAction1); + + verify(view).showContextActions(actions, uiEvent); + } + @Test public void verityVMActionsAreShown() { VmInfo vmInfo = new VmInfo(0, 1, 2, null, null, null, null, null, null, null, null, null, null, null); @@ -505,26 +538,41 @@ when(view.getSelectedHostOrVm()).thenReturn(ref); MouseEvent uiEvent = mock(MouseEvent.class); - ActionEvent viewEvent = new ActionEvent<>(view, MainView.Action.SHOW_VM_CONTEXT_MENU); + ActionEvent viewEvent = new ActionEvent<>(view, MainView.Action.SHOW_HOST_VM_CONTEXT_MENU); viewEvent.setPayload(uiEvent); l.actionPerformed(viewEvent); - verify(view).showVMContextActions(Arrays.asList(action1), uiEvent); + List actions = new ArrayList<>(); + actions.add(vmContextAction1); + + verify(view).showContextActions(actions, uiEvent); } - + + @Test + public void verifyHostActionsAreExecuted() { + HostRef hostRef = mock(HostRef.class); + when(view.getSelectedHostOrVm()).thenReturn(hostRef); + + ActionEvent event = new ActionEvent<>(view, MainView.Action.HOST_VM_CONTEXT_ACTION); + event.setPayload(hostContextAction1); + l.actionPerformed(event); + + verify(hostContextAction1, times(1)).execute(hostRef); + } + @Test public void verityVMActionsAreExecuted() { VmRef vmRef = mock(VmRef.class); when(view.getSelectedHostOrVm()).thenReturn(vmRef); - ActionEvent event = new ActionEvent<>(view, MainView.Action.VM_CONTEXT_ACTION); - event.setPayload(action1); + ActionEvent event = new ActionEvent<>(view, MainView.Action.HOST_VM_CONTEXT_ACTION); + event.setPayload(vmContextAction1); l.actionPerformed(event); - verify(action1, times(1)).execute(any(VmRef.class)); - verify(action2, times(0)).execute(any(VmRef.class)); + verify(vmContextAction1, times(1)).execute(any(VmRef.class)); + verify(vmContextAction2, times(0)).execute(any(VmRef.class)); } @Test diff -r 259c60624174 -r 4f3b798807f3 client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/MainWindowTest.java --- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/MainWindowTest.java Mon Jan 21 13:48:50 2013 -0500 +++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/MainWindowTest.java Mon Jan 21 17:17:28 2013 -0500 @@ -39,6 +39,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.isA; import static org.mockito.Mockito.atLeastOnce; @@ -47,6 +48,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -71,13 +73,14 @@ import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import com.redhat.thermostat.client.core.Filter; +import com.redhat.thermostat.client.osgi.service.ContextAction; import com.redhat.thermostat.client.osgi.service.DecoratorProvider; +import com.redhat.thermostat.client.osgi.service.HostContextAction; import com.redhat.thermostat.client.osgi.service.MenuAction; import com.redhat.thermostat.client.swing.components.SearchField; -import com.redhat.thermostat.client.swing.internal.MainView; -import com.redhat.thermostat.client.swing.internal.MainWindow; import com.redhat.thermostat.client.ui.Decorator; import com.redhat.thermostat.common.ActionEvent; import com.redhat.thermostat.common.ActionListener; @@ -354,4 +357,38 @@ assertEquals(null, window.getSelectedHostOrVm()); } + @GUITest + @Test + public void verifyContextMenu() { + List actions = new ArrayList<>(); + + HostContextAction action = mock(HostContextAction.class); + when(action.getName()).thenReturn("action"); + Filter allMatchingFilter = mock(Filter.class); + when(allMatchingFilter.matches(any(HostRef.class))).thenReturn(true); + + actions.add(action); + + frameFixture.show(); + + // add a second action listener to discard the 'show' event invoked on the first + l = mock(ActionListener.class); + window.addActionListener(l); + + MouseEvent e = new MouseEvent(window, MouseEvent.MOUSE_CLICKED, System.currentTimeMillis(), MouseEvent.BUTTON2_MASK, 0, 0, 0, 0, 1, true, MouseEvent.BUTTON2); + + window.showContextActions(actions, e); + + JMenuItemFixture hostActionMenuItem = frameFixture.menuItem("action"); + hostActionMenuItem.click(); + + ArgumentCaptor actionEventCaptor = ArgumentCaptor.forClass(ActionEvent.class); + verify(l).actionPerformed(actionEventCaptor.capture()); + + ActionEvent actionEvent = actionEventCaptor.getValue(); + assertEquals(window, actionEvent.getSource()); + assertEquals(MainView.Action.HOST_VM_CONTEXT_ACTION, actionEvent.getActionId()); + assertEquals(action, actionEvent.getPayload()); + } + } diff -r 259c60624174 -r 4f3b798807f3 client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/osgi/HostContextActionServiceTrackerTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/osgi/HostContextActionServiceTrackerTest.java Mon Jan 21 17:17:28 2013 -0500 @@ -0,0 +1,70 @@ +/* + * Copyright 2012 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.client.swing.internal.osgi; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import org.junit.Test; +import org.osgi.framework.ServiceRegistration; + +import com.redhat.thermostat.client.osgi.service.HostContextAction; +import com.redhat.thermostat.client.ui.UiFacadeFactory; +import com.redhat.thermostat.test.StubBundleContext; + +public class HostContextActionServiceTrackerTest { + + @Test + public void verifyHostActionIsAddedToAndRemovedFromUiModel() { + StubBundleContext bundleContext = new StubBundleContext(); + UiFacadeFactory applicationModel = mock(UiFacadeFactory.class); + + HostContextAction hostAction = mock(HostContextAction.class); + ServiceRegistration registration = bundleContext.registerService(HostContextAction.class, hostAction, null); + + HostContextActionServiceTracker tracker = new HostContextActionServiceTracker(bundleContext, applicationModel); + tracker.open(); + + registration.unregister(); + + tracker.close(); + + verify(applicationModel).addHostContextAction(hostAction); + verify(applicationModel).removeHostContextAction(hostAction); + } + +} diff -r 259c60624174 -r 4f3b798807f3 client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/osgi/ThermostatActivatorTest.java --- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/osgi/ThermostatActivatorTest.java Mon Jan 21 13:48:50 2013 -0500 +++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/osgi/ThermostatActivatorTest.java Mon Jan 21 17:17:28 2013 -0500 @@ -73,5 +73,7 @@ assertTrue(ctx.isServiceRegistered(ClientConfigViewProvider.class.getName(), SwingClientConfigurationViewProvider.class)); assertEquals(6, ctx.getAllServices().size()); + + // FIXME add more tests for the service tracker used by ThermostatActivator } }