/* * SoapUI, Copyright (C) 2004-2016 SmartBear Software * * Licensed under the EUPL, Version 1.1 or - as soon as they will be approved by the European Commission - subsequent * versions of the EUPL (the "Licence"); * You may not use this work except in compliance with the Licence. * You may obtain a copy of the Licence at: * * http://ec.europa.eu/idabc/eupl * * Unless required by applicable law or agreed to in writing, software distributed under the Licence is * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the Licence for the specific language governing permissions and limitations * under the Licence. */ package com.eviware.soapui; import com.eviware.soapui.impl.WorkspaceImpl; import com.eviware.soapui.impl.actions.ImportWsdlProjectAction; import com.eviware.soapui.impl.actions.SwitchWorkspaceAction; import com.eviware.soapui.impl.wsdl.WsdlProject; import com.eviware.soapui.model.ModelItem; import com.eviware.soapui.model.iface.Interface; import com.eviware.soapui.model.iface.Operation; import com.eviware.soapui.model.iface.Request; import com.eviware.soapui.model.mock.MockOperation; import com.eviware.soapui.model.mock.MockResponse; import com.eviware.soapui.model.mock.MockService; import com.eviware.soapui.model.project.Project; import com.eviware.soapui.model.support.WorkspaceListenerAdapter; import com.eviware.soapui.model.testsuite.LoadTest; import com.eviware.soapui.model.testsuite.TestCase; import com.eviware.soapui.model.testsuite.TestStep; import com.eviware.soapui.model.testsuite.TestSuite; import com.eviware.soapui.model.workspace.Workspace; import com.eviware.soapui.model.workspace.WorkspaceListener; import com.eviware.soapui.support.UISupport; import com.eviware.soapui.support.action.SoapUIActionMapping; import com.eviware.soapui.support.action.support.DefaultActionMapping; import com.eviware.soapui.support.action.swing.SwingActionDelegate; import com.eviware.soapui.support.types.StringToStringMap; import com.eviware.soapui.ui.desktop.DesktopListener; import com.eviware.soapui.ui.desktop.DesktopPanel; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.event.PopupMenuEvent; import javax.swing.event.PopupMenuListener; import java.awt.event.ActionEvent; import java.lang.ref.Reference; import java.lang.ref.WeakReference; import java.util.Map; /** * Workspace/Deskopt Listener that updates the recent menus.. * * @author ole.matzura */ public class RecentItemsListener extends WorkspaceListenerAdapter implements WorkspaceListener, DesktopListener { private static final String RECENT_WORKSPACES_SETTING = "RecentWorkspaces"; private static final String RECENT_PROJECTS_SETTING = "RecentProjects"; private static final String EMPTYMARKER = "- empty -"; private static final String CLEAR_ITEMS = "Clear Items"; private JMenu recentProjectsMenu; private JMenu recentWorkspacesMenu; private JMenu recentEditorsMenu; private boolean switchingWorkspace; public RecentItemsListener(JMenu recentWorkspacesMenu2, JMenu recentProjectsMenu2, JMenu recentEditorsMenu2) { recentWorkspacesMenu = recentWorkspacesMenu2; recentProjectsMenu = recentProjectsMenu2; recentEditorsMenu = recentEditorsMenu2; recentEditorsMenu.add(EMPTYMARKER).setEnabled(false); recentEditorsMenu.getPopupMenu().addPopupMenuListener(new PopupMenuListener() { public void popupMenuCanceled(PopupMenuEvent e) { } public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { } public void popupMenuWillBecomeVisible(PopupMenuEvent e) { int editorCount = 0; for (int c = 0; c < recentEditorsMenu.getItemCount(); c++) { ShowEditorAction action = getShowEditorAction(recentEditorsMenu, c); if (action == null) { continue; } editorCount++; if (action.isReleased()) { recentEditorsMenu.remove(c); c--; } else { try { action.update(); } catch (Throwable e1) { recentEditorsMenu.remove(c); c--; } } } // Look for a Clear Items JMenuItem, and create it if not existing JMenuItem clearAllItem = null; for (int i = 0; i < recentEditorsMenu.getItemCount(); ++i) { JMenuItem editorItem = recentEditorsMenu.getItem(i); if (editorItem == null) { continue; } if (editorItem.getText().equals(CLEAR_ITEMS)) { clearAllItem = editorItem; } } if (clearAllItem == null) { clearAllItem = new JMenuItem(new ClearEditorsAction()); recentEditorsMenu.addSeparator(); recentEditorsMenu.add(clearAllItem); } clearAllItem.setEnabled(editorCount > 0); // Create Empty Marker if needed. if (editorCount == 0 && recentEditorsMenu.getItemCount() <= 2) { recentEditorsMenu.add(new JMenuItem(EMPTYMARKER), 0).setEnabled(false); } } }); updateRecentWorkspacesMenu(); updateRecentProjectsMenu(); } @SuppressWarnings("unchecked") private void updateRecentWorkspacesMenu() { String recent = SoapUI.getSettings().getString(RECENT_WORKSPACES_SETTING, null); StringToStringMap history = recent == null ? new StringToStringMap() : StringToStringMap.fromXml(recent); recentWorkspacesMenu.removeAll(); if (history.size() > 0) { for (Map.Entry<String, String> entry : history.entrySet()) { String filePath = entry.getKey(); DefaultActionMapping<WorkspaceImpl> mapping = new DefaultActionMapping<WorkspaceImpl>( SwitchWorkspaceAction.SOAPUI_ACTION_ID, null, null, false, filePath); String wsName = entry.getValue(); if (SoapUI.getWorkspace().getPath().equals(filePath)) { continue; } mapping.setName(wsName); mapping.setDescription("Switches to the [" + wsName + "] workspace"); AbstractAction delegate = new SwingActionDelegate(mapping, SoapUI.getWorkspace()); recentWorkspacesMenu.add(new JMenuItem(delegate)); } } else { recentWorkspacesMenu.add(EMPTYMARKER).setEnabled(false); } recentWorkspacesMenu.addSeparator(); recentWorkspacesMenu.add(new ClearWorkspacesAction()).setEnabled(history.size() > 0); } @SuppressWarnings("unchecked") private void updateRecentProjectsMenu() { recentProjectsMenu.removeAll(); String recent = SoapUI.getSettings().getString(RECENT_PROJECTS_SETTING, null); StringToStringMap history = recent == null ? new StringToStringMap() : StringToStringMap.fromXml(recent); if (history.size() > 0) { for (Map.Entry<String, String> entry : history.entrySet()) { String filePath = entry.getKey(); DefaultActionMapping<WorkspaceImpl> mapping = new DefaultActionMapping<WorkspaceImpl>( ImportWsdlProjectAction.SOAPUI_ACTION_ID, null, null, false, filePath); String wsName = entry.getValue(); mapping.setName(wsName); mapping.setDescription("Switches to the [" + wsName + "] project"); AbstractAction delegate = new SwingActionDelegate(mapping, SoapUI.getWorkspace()); recentProjectsMenu.add(new JMenuItem(delegate)); } } else { recentProjectsMenu.add(EMPTYMARKER).setEnabled(false); } recentProjectsMenu.addSeparator(); recentProjectsMenu.add(new ClearProjectsAction()).setEnabled(history.size() > 0); } @SuppressWarnings("unchecked") public void projectAdded(Project project) { if (switchingWorkspace) { return; } String filePath = ((WsdlProject) project).getPath(); if (filePath == null) { return; } String recent = SoapUI.getSettings().getString(RECENT_PROJECTS_SETTING, null); if (recent != null) { StringToStringMap history = StringToStringMap.fromXml(recent); history.remove(filePath); SoapUI.getSettings().setString(RECENT_PROJECTS_SETTING, history.toXml()); } for (int c = 0; c < recentProjectsMenu.getItemCount() - 2; c++) { JMenuItem item = recentProjectsMenu.getItem(c); if (item == null) { continue; } Action action = item.getAction(); if (!(action instanceof SwingActionDelegate)) { continue; } SwingActionDelegate actionDelegate = (SwingActionDelegate) action; if (actionDelegate == null) { continue; } SoapUIActionMapping mapping = actionDelegate.getMapping(); if (filePath.equals(mapping.getParam())) { recentProjectsMenu.remove(c); break; } } if (recentProjectsMenu.getItemCount() == 2) { recentProjectsMenu.add(new JMenuItem(EMPTYMARKER), 0).setEnabled(false); recentProjectsMenu.getItem(recentProjectsMenu.getItemCount() - 1).setEnabled(false); } } public void projectChanged(Project project) { } @SuppressWarnings("unchecked") public void projectRemoved(Project project) { if (switchingWorkspace) { return; } String filePath = ((WsdlProject) project).getPath(); String recent = SoapUI.getSettings().getString(RECENT_PROJECTS_SETTING, null); StringToStringMap history = recent == null ? new StringToStringMap() : StringToStringMap.fromXml(recent); history.put(filePath, project.getName()); SoapUI.getSettings().setString(RECENT_PROJECTS_SETTING, history.toXml()); DefaultActionMapping<WorkspaceImpl> mapping = new DefaultActionMapping<WorkspaceImpl>( ImportWsdlProjectAction.SOAPUI_ACTION_ID, null, null, false, filePath); mapping.setName(project.getName()); mapping.setDescription("Switches to the [" + project.getName() + "] project"); AbstractAction delegate = new SwingActionDelegate(mapping, SoapUI.getWorkspace()); recentProjectsMenu.add(new JMenuItem(delegate), recentProjectsMenu.getItemCount() - 2); recentProjectsMenu.getItem(recentProjectsMenu.getItemCount() - 1).setEnabled(true); if (isEmptyMarker(recentProjectsMenu.getItem(0))) { recentProjectsMenu.remove(0); } removeProjectEditors(project); } private void removeProjectEditors(Project project) { for (int c = 0; c < recentEditorsMenu.getItemCount(); c++) { ShowEditorAction action = getShowEditorAction(recentEditorsMenu, c); if (action == null) { continue; } if (action.isReleased()) { recentEditorsMenu.remove(c); c--; } else { try { action.update(); if (dependsOnProject(action.getModelItem(), project)) { recentEditorsMenu.remove(c); c--; } } catch (Throwable e1) { recentEditorsMenu.remove(c); c--; } } } } private boolean dependsOnProject(ModelItem modelItem, Project project) { if (modelItem instanceof Interface) { return ((Interface) modelItem).getProject() == project; } else if (modelItem instanceof Operation) { return ((Operation) modelItem).getInterface().getProject() == project; } else if (modelItem instanceof Request) { return ((Request) modelItem).getOperation().getInterface().getProject() == project; } else if (modelItem instanceof TestSuite) { return ((TestSuite) modelItem).getProject() == project; } else if (modelItem instanceof TestCase) { return ((TestCase) modelItem).getTestSuite().getProject() == project; } else if (modelItem instanceof TestStep) { return ((TestStep) modelItem).getTestCase().getTestSuite().getProject() == project; } else if (modelItem instanceof LoadTest) { return ((LoadTest) modelItem).getTestCase().getTestSuite().getProject() == project; } else if (modelItem instanceof MockService) { return ((MockService) modelItem).getProject() == project; } else if (modelItem instanceof MockOperation) { return ((MockOperation) modelItem).getMockService().getProject() == project; } else if (modelItem instanceof MockResponse) { return ((MockResponse) modelItem).getMockOperation().getMockService().getProject() == project; } return false; } @SuppressWarnings("unchecked") public void workspaceSwitched(Workspace workspace) { switchingWorkspace = false; String filePath = workspace.getPath(); String recent = SoapUI.getSettings().getString(RECENT_WORKSPACES_SETTING, null); if (recent != null) { StringToStringMap history = StringToStringMap.fromXml(recent); history.remove(filePath); SoapUI.getSettings().setString(RECENT_WORKSPACES_SETTING, history.toXml()); } for (int c = 0; c < recentWorkspacesMenu.getItemCount(); c++) { JMenuItem item = recentWorkspacesMenu.getItem(c); if (item == null) { continue; } Action action = item.getAction(); if (!(action instanceof SwingActionDelegate)) { continue; } SwingActionDelegate actionDelegate = (SwingActionDelegate) action; if (actionDelegate == null) { continue; } SoapUIActionMapping mapping = actionDelegate.getMapping(); if (filePath.equals(mapping.getParam())) { recentWorkspacesMenu.remove(c); break; } } if (recentWorkspacesMenu.getItemCount() == 2) { recentWorkspacesMenu.add(new JMenuItem(EMPTYMARKER), 0).setEnabled(false); } } @SuppressWarnings("unchecked") public void workspaceSwitching(Workspace workspace) { switchingWorkspace = true; recentEditorsMenu.removeAll(); if (recentEditorsMenu.getItemCount() == 0) { recentEditorsMenu.add(EMPTYMARKER).setEnabled(false); } String filePath = workspace.getPath(); DefaultActionMapping<WorkspaceImpl> mapping = new DefaultActionMapping<WorkspaceImpl>( SwitchWorkspaceAction.SOAPUI_ACTION_ID, null, null, false, filePath); mapping.setName(workspace.getName()); mapping.setDescription("Switches to the [" + workspace.getName() + "] workspace"); AbstractAction delegate = new SwingActionDelegate(mapping, SoapUI.getWorkspace()); recentWorkspacesMenu.add(new JMenuItem(delegate), recentWorkspacesMenu.getItemCount() - 2); recentWorkspacesMenu.getItem(recentWorkspacesMenu.getItemCount() - 1).setEnabled(true); System.out.println(recentWorkspacesMenu.getItem(recentWorkspacesMenu.getItemCount() - 1).getText()); String recent = SoapUI.getSettings().getString(RECENT_WORKSPACES_SETTING, null); StringToStringMap history = recent == null ? new StringToStringMap() : StringToStringMap.fromXml(recent); history.put(filePath, workspace.getName()); SoapUI.getSettings().setString(RECENT_WORKSPACES_SETTING, history.toXml()); if (isEmptyMarker(recentWorkspacesMenu.getItem(0))) { recentWorkspacesMenu.remove(0); } recentEditorsMenu.removeAll(); } public void desktopPanelClosed(DesktopPanel desktopPanel) { ModelItem modelItem = desktopPanel.getModelItem(); if (modelItem == null || recentEditorsMenu.getItemCount() == 0) { return; } if (isEmptyMarker(recentEditorsMenu.getItem(0))) { recentEditorsMenu.remove(0); } recentEditorsMenu.add(new JMenuItem(new ShowEditorAction(modelItem)), 0); } public void desktopPanelCreated(DesktopPanel desktopPanel) { for (int c = 0; c < recentEditorsMenu.getItemCount(); c++) { ShowEditorAction action = getShowEditorAction(recentEditorsMenu, c); if (action == null) { continue; } if (action.isReleased()) { recentEditorsMenu.remove(c); c--; } else if (action.getModelItem().equals(desktopPanel.getModelItem())) { recentEditorsMenu.remove(c); break; } } if (recentEditorsMenu.getItemCount() == 2) { recentEditorsMenu.add(new JMenuItem(EMPTYMARKER), 0).setEnabled(false); } } public void desktopPanelSelected(DesktopPanel desktopPanel) { } private static class ShowEditorAction extends AbstractAction { private Reference<ModelItem> ref; public ShowEditorAction(ModelItem modelItem) { super(modelItem.getName()); putValue(Action.SHORT_DESCRIPTION, "Reopen editor for [" + modelItem.getName() + "]"); ref = new WeakReference<ModelItem>(modelItem); } public ModelItem getModelItem() { return ref.get(); } public void update() { ModelItem modelItem = ref.get(); if (modelItem == null) { return; } putValue(Action.NAME, modelItem.getName()); putValue(Action.SHORT_DESCRIPTION, "Reopen editor for [" + modelItem.getName() + "]"); } public boolean isReleased() { return ref.get() == null; } public void actionPerformed(ActionEvent e) { ModelItem modelItem = ref.get(); if (modelItem != null) { UISupport.showDesktopPanel(modelItem); } else { UISupport.showErrorMessage("Item [" + getValue(Action.NAME) + "] is no longer available"); } } } /* Helper methods */ /** * Confirms that the item of index i in menu is a ShowEditorAction, and * extracts the ShowEditorAction. * * @param menu The menu to get the JMenuItem, containing the action from. * @param i The index where the JMenuItem is located in menu. * @return The ShowEditorAction if confirmed. Otherwise null. */ private ShowEditorAction getShowEditorAction(JMenu menu, int i) { JMenuItem menuItem = recentEditorsMenu.getItem(i); if (menuItem == null) { return null; } Action unknownAction = menuItem.getAction(); if (unknownAction == null || !(unknownAction instanceof ShowEditorAction)) { return null; } return (ShowEditorAction) unknownAction; } /** * Checks whether a JMenuItem is an Empty marker (marking an empty list). * * @param item The item to check. * @return True if item is an Empty marker. False otherwise (including if * item is null). */ private boolean isEmptyMarker(JMenuItem item) { if (item == null) { return false; } if (item.getText().equals(EMPTYMARKER)) { return true; } return false; } /* * Action classes for clearing all items in the Recent * Editors/Projects/Workspaces submenu */ @SuppressWarnings("serial") private class ClearProjectsAction extends AbstractAction { public ClearProjectsAction() { super(CLEAR_ITEMS); putValue(Action.SHORT_DESCRIPTION, "Clear all recent projects"); } public void actionPerformed(ActionEvent e) { if (!UISupport.confirm("Remove all Projects from this menu?", "Question")) { return; } StringToStringMap emptyMap = new StringToStringMap(); SoapUI.getSettings().setString(RECENT_PROJECTS_SETTING, emptyMap.toXml()); updateRecentProjectsMenu(); } } @SuppressWarnings("serial") private class ClearWorkspacesAction extends AbstractAction { public ClearWorkspacesAction() { super(CLEAR_ITEMS); putValue(Action.SHORT_DESCRIPTION, "Clear all recent workspaces"); } public void actionPerformed(ActionEvent e) { if (!UISupport.confirm("Remove all Workspaces from this menu?", "Question")) { return; } StringToStringMap emptyMap = new StringToStringMap(); SoapUI.getSettings().setString(RECENT_WORKSPACES_SETTING, emptyMap.toXml()); updateRecentWorkspacesMenu(); } } @SuppressWarnings("serial") private class ClearEditorsAction extends AbstractAction { public ClearEditorsAction() { super(CLEAR_ITEMS); putValue(Action.SHORT_DESCRIPTION, "Clear all recent Editors"); } public void actionPerformed(ActionEvent e) { if (!UISupport.confirm("Remove all Editors from this menu?", "Question")) { return; } recentEditorsMenu.removeAll(); recentEditorsMenu.add(EMPTYMARKER).setEnabled(false); recentEditorsMenu.addSeparator(); recentEditorsMenu.add(new ClearEditorsAction()); } } }