Java tutorial
/* * Copyright (c) Mirth Corporation. All rights reserved. * * http://www.mirthcorp.com * * The software in this package is published under the terms of the MPL license a copy of which has * been included with this distribution in the LICENSE.txt file. */ package com.mirth.connect.client.ui; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Cursor; import java.awt.Dimension; import java.awt.Font; import java.awt.GradientPaint; import java.awt.KeyEventDispatcher; import java.awt.KeyboardFocusManager; import java.awt.Toolkit; import java.awt.Window; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.UUID; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.prefs.Preferences; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.swing.Action; import javax.swing.BorderFactory; import javax.swing.ImageIcon; import javax.swing.JCheckBox; import javax.swing.JFileChooser; import javax.swing.JLabel; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.SwingUtilities; import javax.swing.SwingWorker; import javax.swing.border.LineBorder; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.http.conn.HttpHostConnectException; import org.apache.log4j.Logger; import org.fife.rsta.ac.LanguageSupportFactory; import org.fife.ui.rsyntaxtextarea.SyntaxConstants; import org.jdesktop.swingx.JXFrame; import org.jdesktop.swingx.JXHyperlink; import org.jdesktop.swingx.JXTaskPane; import org.jdesktop.swingx.JXTaskPaneContainer; import org.jdesktop.swingx.JXTitledPanel; import org.jdesktop.swingx.action.ActionFactory; import org.jdesktop.swingx.action.ActionManager; import org.jdesktop.swingx.action.BoundAction; import org.jdesktop.swingx.painter.MattePainter; import org.syntax.jedit.JEditTextArea; import com.mirth.connect.client.core.Client; import com.mirth.connect.client.core.ClientException; import com.mirth.connect.client.core.ConnectServiceUtil; import com.mirth.connect.client.core.ForbiddenException; import com.mirth.connect.client.core.RequestAbortedException; import com.mirth.connect.client.core.TaskConstants; import com.mirth.connect.client.core.UnauthorizedException; import com.mirth.connect.client.core.Version; import com.mirth.connect.client.core.VersionMismatchException; import com.mirth.connect.client.ui.DashboardPanel.TableState; import com.mirth.connect.client.ui.alert.AlertEditPanel; import com.mirth.connect.client.ui.alert.AlertPanel; import com.mirth.connect.client.ui.alert.DefaultAlertEditPanel; import com.mirth.connect.client.ui.alert.DefaultAlertPanel; import com.mirth.connect.client.ui.browsers.event.EventBrowser; import com.mirth.connect.client.ui.browsers.message.MessageBrowser; import com.mirth.connect.client.ui.codetemplate.CodeTemplatePanel; import com.mirth.connect.client.ui.components.rsta.ac.js.MirthJavaScriptLanguageSupport; import com.mirth.connect.client.ui.dependencies.ChannelDependenciesWarningDialog; import com.mirth.connect.client.ui.extensionmanager.ExtensionManagerPanel; import com.mirth.connect.donkey.model.channel.DeployedState; import com.mirth.connect.donkey.model.channel.DestinationConnectorPropertiesInterface; import com.mirth.connect.donkey.model.channel.MetaDataColumn; import com.mirth.connect.donkey.model.channel.SourceConnectorPropertiesInterface; import com.mirth.connect.donkey.model.message.RawMessage; import com.mirth.connect.model.ApiProvider; import com.mirth.connect.model.Channel; import com.mirth.connect.model.ChannelHeader; import com.mirth.connect.model.ChannelStatus; import com.mirth.connect.model.Connector; import com.mirth.connect.model.Connector.Mode; import com.mirth.connect.model.ConnectorMetaData; import com.mirth.connect.model.DashboardChannelInfo; import com.mirth.connect.model.DashboardStatus; import com.mirth.connect.model.DashboardStatus.StatusType; import com.mirth.connect.model.EncryptionSettings; import com.mirth.connect.model.InvalidChannel; import com.mirth.connect.model.MetaData; import com.mirth.connect.model.PluginMetaData; import com.mirth.connect.model.ResourceProperties; import com.mirth.connect.model.ServerSettings; import com.mirth.connect.model.UpdateSettings; import com.mirth.connect.model.User; import com.mirth.connect.model.alert.AlertInfo; import com.mirth.connect.model.alert.AlertModel; import com.mirth.connect.model.alert.AlertStatus; import com.mirth.connect.model.converters.ObjectXMLSerializer; import com.mirth.connect.model.filters.MessageFilter; import com.mirth.connect.plugins.DashboardColumnPlugin; import com.mirth.connect.plugins.DataTypeClientPlugin; import com.mirth.connect.util.ChannelDependencyException; import com.mirth.connect.util.ChannelDependencyGraph; import com.mirth.connect.util.DirectedAcyclicGraphNode; import com.mirth.connect.util.MigrationUtil; /** * The main content frame for the Mirth Client Application. Extends JXFrame and sets up all content. */ public class Frame extends JXFrame { private Logger logger = Logger.getLogger(this.getClass()); public Client mirthClient; public DashboardPanel dashboardPanel = null; public ChannelPanel channelPanel = null; public SettingsPane settingsPane = null; public UserPanel userPanel = null; public ChannelSetup channelEditPanel = null; public EventBrowser eventBrowser = null; public MessageBrowser messageBrowser = null; public AlertPanel alertPanel = null; public AlertEditPanel alertEditPanel = null; public CodeTemplatePanel codeTemplatePanel = null; public GlobalScriptsPanel globalScriptsPanel = null; public ExtensionManagerPanel extensionsPanel = null; public JXTaskPaneContainer taskPaneContainer; public List<DashboardStatus> status = null; public List<User> users = null; public ActionManager manager = ActionManager.getInstance(); public JPanel contentPanel; public BorderLayout borderLayout1 = new BorderLayout(); public StatusBar statusBar; public JSplitPane splitPane = new JSplitPane(); public JScrollPane taskPane = new JScrollPane(); public JScrollPane contentPane = new JScrollPane(); public Component currentContentPage = null; public JXTaskPaneContainer currentTaskPaneContainer = null; public JScrollPane container; public EditMessageDialog editMessageDialog = null; // Task panes and popup menus public JXTaskPane viewPane; public JXTaskPane otherPane; public JXTaskPane dashboardTasks; public JPopupMenu dashboardPopupMenu; public JXTaskPane eventTasks; public JPopupMenu eventPopupMenu; public JXTaskPane messageTasks; public JPopupMenu messagePopupMenu; public JXTaskPane details; public JXTaskPane channelEditTasks; public JPopupMenu channelEditPopupMenu; public JXTaskPane userTasks; public JPopupMenu userPopupMenu; public JXTaskPane alertTasks; public JPopupMenu alertPopupMenu; public JXTaskPane alertEditTasks; public JPopupMenu alertEditPopupMenu; public JXTaskPane globalScriptsTasks; public JPopupMenu globalScriptsPopupMenu; public JXTaskPane extensionsTasks; public JPopupMenu extensionsPopupMenu; public JXTitledPanel rightContainer; private ExecutorService statusUpdaterExecutor = Executors.newSingleThreadExecutor(); private Future<?> statusUpdaterJob = null; public static Preferences userPreferences; private boolean connectionError; private ArrayList<CharsetEncodingInformation> availableCharsetEncodings = null; private List<String> charsetEncodings = null; public boolean isEditingChannel = false; private boolean isEditingAlert = false; private LinkedHashMap<String, String> workingStatuses = new LinkedHashMap<String, String>(); public LinkedHashMap<String, String> dataTypeToDisplayName; public LinkedHashMap<String, String> displayNameToDataType; private Map<String, PluginMetaData> loadedPlugins; private Map<String, ConnectorMetaData> loadedConnectors; private Map<String, Integer> safeErrorFailCountMap = new HashMap<String, Integer>(); private Map<Component, String> componentTaskMap = new HashMap<Component, String>(); private boolean acceleratorKeyPressed = false; private boolean canSave = true; private ChannelTagInfo channelTagInfo; private ChannelTagInfo deployedChannelTagInfo; private RemoveMessagesDialog removeMessagesDialog; private MessageExportDialog messageExportDialog; private MessageImportDialog messageImportDialog; private AttachmentExportDialog attachmentExportDialog; private KeyEventDispatcher keyEventDispatcher = null; private static final int REFRESH_BLOCK_SIZE = 100; public Frame() { // Load RSyntaxTextArea language support LanguageSupportFactory.get().addLanguageSupport(SyntaxConstants.SYNTAX_STYLE_JAVASCRIPT, MirthJavaScriptLanguageSupport.class.getName()); rightContainer = new JXTitledPanel(); channelTagInfo = new ChannelTagInfo(); deployedChannelTagInfo = new ChannelTagInfo(); taskPaneContainer = new JXTaskPaneContainer(); StringBuilder titleText = new StringBuilder(); if (!StringUtils.isBlank(PlatformUI.SERVER_NAME)) { titleText.append(PlatformUI.SERVER_NAME); } else { titleText.append(PlatformUI.SERVER_URL); } titleText.append(" - " + UIConstants.TITLE_TEXT); setTitle(titleText.toString()); setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); setIconImage(new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/mirth_32_ico.png")) .getImage()); makePaneContainer(); connectionError = false; this.addComponentListener(new ComponentListener() { public void componentResized(ComponentEvent e) { if (channelEditPanel != null && channelEditPanel.filterPane != null) { channelEditPanel.filterPane.resizePanes(); } if (channelEditPanel != null && channelEditPanel.transformerPane != null) { channelEditPanel.transformerPane.resizePanes(); } } public void componentHidden(ComponentEvent e) { } public void componentShown(ComponentEvent e) { } public void componentMoved(ComponentEvent e) { } }); this.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { if (logout(true)) { System.exit(0); } } }); keyEventDispatcher = new KeyEventDispatcher() { @Override public boolean dispatchKeyEvent(KeyEvent e) { // Update the state of the accelerator key (CTRL on Windows) updateAcceleratorKeyPressed(e); return false; } }; KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(keyEventDispatcher); } /** * Prepares the list of the encodings. This method is called from the Frame class. * */ public void setCharsetEncodings() { if (this.availableCharsetEncodings != null) { return; } try { this.charsetEncodings = this.mirthClient.getAvailableCharsetEncodings(); this.availableCharsetEncodings = new ArrayList<CharsetEncodingInformation>(); this.availableCharsetEncodings .add(new CharsetEncodingInformation(UIConstants.DEFAULT_ENCODING_OPTION, "Default")); for (int i = 0; i < charsetEncodings.size(); i++) { String canonical = charsetEncodings.get(i); this.availableCharsetEncodings.add(new CharsetEncodingInformation(canonical, canonical)); } } catch (Exception e) { alertError(this, "Error getting the charset list:\n " + e); } } /** * Creates all the items in the combo box for the connectors. * * This method is called from each connector. */ public void setupCharsetEncodingForConnector(javax.swing.JComboBox charsetEncodingCombobox) { if (this.availableCharsetEncodings == null) { this.setCharsetEncodings(); } if (this.availableCharsetEncodings == null) { logger.error("Error, the are no encodings detected."); return; } charsetEncodingCombobox.removeAllItems(); for (int i = 0; i < this.availableCharsetEncodings.size(); i++) { charsetEncodingCombobox.addItem(this.availableCharsetEncodings.get(i)); } } /** * Sets the combobox for the string previously selected. If the server can't support the * encoding, the default one is selected. This method is called from each connector. */ public void setPreviousSelectedEncodingForConnector(javax.swing.JComboBox charsetEncodingCombobox, String selectedCharset) { if (this.availableCharsetEncodings == null) { this.setCharsetEncodings(); } if (this.availableCharsetEncodings == null) { logger.error("Error, there are no encodings detected."); return; } if ((selectedCharset == null) || (selectedCharset.equalsIgnoreCase(UIConstants.DEFAULT_ENCODING_OPTION))) { charsetEncodingCombobox.setSelectedIndex(0); } else if (this.charsetEncodings.contains(selectedCharset)) { int index = this.availableCharsetEncodings .indexOf(new CharsetEncodingInformation(selectedCharset, selectedCharset)); if (index < 0) { logger.error("Synchronization lost in the list of the encoding characters."); index = 0; } charsetEncodingCombobox.setSelectedIndex(index); } else { alertInformation(this, "Sorry, the JVM of the server can't support the previously selected " + selectedCharset + " encoding. Please choose another one or install more encodings in the server."); charsetEncodingCombobox.setSelectedIndex(0); } } /** * Get the strings which identifies the encoding selected by the user. * * This method is called from each connector. */ public String getSelectedEncodingForConnector(javax.swing.JComboBox charsetEncodingCombobox) { try { return ((CharsetEncodingInformation) charsetEncodingCombobox.getSelectedItem()).getCanonicalName(); } catch (Throwable t) { alertInformation(this, "Error " + t); return UIConstants.DEFAULT_ENCODING_OPTION; } } /** * Called to set up this main window frame. */ public void setupFrame(Client mirthClient) throws ClientException { LoginPanel login = LoginPanel.getInstance(); // Initialize the send message dialog editMessageDialog = new EditMessageDialog(); this.mirthClient = mirthClient; login.setStatus("Loading extensions..."); try { loadExtensionMetaData(); } catch (ClientException e) { alertError(this, "Unable to load extensions."); throw e; } // Re-initialize the controller every time the frame is setup AuthorizationControllerFactory.getAuthorizationController().initialize(); channelPanel = new ChannelPanel(); channelPanel.retrieveGroups(); channelPanel.retrieveDependencies(); // Initialize all of the extensions now that the metadata has been retrieved // Make sure to initialize before the code template panel is created because it needs extensions LoadedExtensions.getInstance().initialize(); codeTemplatePanel = new CodeTemplatePanel(this); // Now it's okay to start the plugins LoadedExtensions.getInstance().startPlugins(); statusBar = new StatusBar(); statusBar.setBorder(BorderFactory.createEmptyBorder()); channelPanel.initPanelPlugins(); // Load the data type/display name maps now that the extensions have been loaded. dataTypeToDisplayName = new LinkedHashMap<String, String>(); displayNameToDataType = new LinkedHashMap<String, String>(); for (Entry<String, DataTypeClientPlugin> entry : LoadedExtensions.getInstance().getDataTypePlugins() .entrySet()) { dataTypeToDisplayName.put(entry.getKey(), entry.getValue().getDisplayName()); displayNameToDataType.put(entry.getValue().getDisplayName(), entry.getKey()); } setInitialVisibleTasks(); login.setStatus("Loading preferences..."); userPreferences = Preferences.userNodeForPackage(Mirth.class); userPreferences.put("defaultServer", PlatformUI.SERVER_URL); login.setStatus("Loading GUI components..."); splitPane.setDividerSize(0); splitPane.setBorder(BorderFactory.createEmptyBorder()); contentPanel = (JPanel) getContentPane(); contentPanel.setLayout(new BorderLayout()); contentPanel.setBorder(BorderFactory.createEmptyBorder()); taskPane.setBorder(BorderFactory.createEmptyBorder()); contentPane.setBorder(BorderFactory.createEmptyBorder()); buildContentPanel(rightContainer, contentPane, false); // Set task pane container background painter MattePainter taskPanePainter = new MattePainter(new GradientPaint(0f, 0f, UIConstants.JX_CONTAINER_BACKGROUND_COLOR, 0f, 1f, UIConstants.JX_CONTAINER_BACKGROUND_COLOR)); taskPanePainter.setPaintStretched(true); taskPaneContainer.setBackgroundPainter(taskPanePainter); // Set main content container title painter MattePainter contentTitlePainter = new MattePainter(new GradientPaint(0f, 0f, UIConstants.JX_CONTAINER_BACKGROUND_COLOR, 0f, 1f, UIConstants.JX_CONTAINER_BACKGROUND_COLOR)); contentTitlePainter.setPaintStretched(true); rightContainer.setTitlePainter(contentTitlePainter); splitPane.add(rightContainer, JSplitPane.RIGHT); splitPane.add(taskPane, JSplitPane.LEFT); taskPane.setMinimumSize(new Dimension(UIConstants.TASK_PANE_WIDTH, 0)); splitPane.setDividerLocation(UIConstants.TASK_PANE_WIDTH); contentPanel.add(statusBar, BorderLayout.SOUTH); contentPanel.add(splitPane, java.awt.BorderLayout.CENTER); try { PlatformUI.SERVER_ID = mirthClient.getServerId(); PlatformUI.SERVER_VERSION = mirthClient.getVersion(); PlatformUI.SERVER_TIMEZONE = mirthClient.getServerTimezone(); PlatformUI.SERVER_TIME = mirthClient.getServerTime(); setTitle(getTitle() + " - (" + PlatformUI.SERVER_VERSION + ")"); PlatformUI.BUILD_DATE = mirthClient.getBuildDate(); // Initialize ObjectXMLSerializer once we know the server version try { ObjectXMLSerializer.getInstance().init(PlatformUI.SERVER_VERSION); } catch (Exception e) { } } catch (ClientException e) { alertError(this, "Could not get server information."); } // Display the server timezone information statusBar.setTimezoneText(PlatformUI.SERVER_TIMEZONE); statusBar.setServerTime(PlatformUI.SERVER_TIME); setCurrentTaskPaneContainer(taskPaneContainer); login.setStatus("Loading dashboard..."); doShowDashboard(); login.setStatus("Loading channel editor..."); channelEditPanel = new ChannelSetup(); login.setStatus("Loading alert editor..."); if (alertEditPanel == null) { alertEditPanel = new DefaultAlertEditPanel(); } login.setStatus("Loading message browser..."); messageBrowser = new MessageBrowser(); // Refresh code templates after extensions have been loaded codeTemplatePanel.doRefreshCodeTemplates(false); // Refresh resources if (settingsPane == null) { settingsPane = new SettingsPane(); } SettingsPanelResources resourcesPanel = (SettingsPanelResources) settingsPane .getSettingsPanel(SettingsPanelResources.TAB_NAME); if (resourcesPanel != null) { resourcesPanel.doRefresh(); } // DEBUGGING THE UIDefaults: // UIDefaults uiDefaults = UIManager.getDefaults(); Enumeration enum1 = // uiDefaults.keys(); while (enum1.hasMoreElements()) { Object key = // enum1.nextElement(); Object val = uiDefaults.get(key); //// if(key.toString().indexOf("ComboBox") != -1) // System.out.println("UIManager.put(\"" + key.toString() + "\",\"" + // (null != val ? val.toString() : "(null)") + "\");"); } } private void loadExtensionMetaData() throws ClientException { loadedPlugins = mirthClient.getPluginMetaData(); loadedConnectors = mirthClient.getConnectorMetaData(); // Register extension JAX-RS providers with the client Set<String> apiProviderPackages = new HashSet<String>(); Set<String> apiProviderClasses = new HashSet<String>(); for (Object extensionMetaData : CollectionUtils.union(loadedPlugins.values(), loadedConnectors.values())) { MetaData metaData = (MetaData) extensionMetaData; for (ApiProvider provider : metaData.getApiProviders(Version.getLatest())) { switch (provider.getType()) { case SERVLET_INTERFACE_PACKAGE: case CORE_PACKAGE: apiProviderPackages.add(provider.getName()); break; case SERVLET_INTERFACE: case CORE_CLASS: apiProviderClasses.add(provider.getName()); break; default: } } } mirthClient.registerApiProviders(apiProviderPackages, apiProviderClasses); } /** * Builds the content panel with a title bar and settings. */ private void buildContentPanel(JXTitledPanel container, JScrollPane component, boolean opaque) { container.getContentContainer().setLayout(new BorderLayout()); container.setBorder(null); container.setTitleFont(new Font("Tahoma", Font.BOLD, 18)); container.setTitleForeground(UIConstants.HEADER_TITLE_TEXT_COLOR); JLabel mirthConnectImage = new JLabel(); mirthConnectImage.setIcon(UIConstants.MIRTHCONNECT_LOGO_GRAY); mirthConnectImage.setText(" "); mirthConnectImage.setToolTipText(UIConstants.MIRTHCONNECT_TOOLTIP); mirthConnectImage.setCursor(new Cursor(Cursor.HAND_CURSOR)); mirthConnectImage.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseClicked(java.awt.event.MouseEvent evt) { BareBonesBrowserLaunch.openURL(UIConstants.MIRTHCONNECT_URL); } }); ((JPanel) container.getComponent(0)).add(mirthConnectImage); component.setBorder(new LineBorder(Color.GRAY, 1)); component.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); component.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER); container.getContentContainer().add(component); } /** * Set the main content panel title to a String */ public void setPanelName(String name) { rightContainer.setTitle(name); statusBar.setStatusText(""); } public String startWorking(final String displayText) { String id = null; synchronized (workingStatuses) { if (statusBar != null) { id = UUID.randomUUID().toString(); workingStatuses.put(id, displayText); statusBar.setWorking(true); statusBar.setText(displayText); } } return id; } public void stopWorking(final String workingId) { synchronized (workingStatuses) { if ((statusBar != null) && (workingId != null)) { workingStatuses.remove(workingId); if (workingStatuses.size() > 0) { statusBar.setWorking(true); statusBar.setText(new LinkedList<String>(workingStatuses.values()).getLast()); } else { statusBar.setWorking(false); statusBar.setText(""); } } } } /** * Changes the current content page to the Channel Editor with the new channel specified as the * loaded one. */ public void setupChannel(Channel channel, String groupId) { setBold(viewPane, UIConstants.ERROR_CONSTANT); setCurrentContentPage(channelEditPanel); setFocus(channelEditTasks); setVisibleTasks(channelEditTasks, channelEditPopupMenu, 0, 0, false); channelEditPanel.addChannel(channel, groupId); } /** * Edits a channel at a specified index, setting that channel as the current channel in the * editor. */ public void editChannel(Channel channel) { String alertMessage = channelEditPanel.checkInvalidPluginProperties(channel); if (StringUtils.isNotBlank(alertMessage)) { if (!alertOption(this, alertMessage + "\nWhen this channel is saved, those properties will be lost. You can choose to import/edit\nthis channel at a later time after verifying that all necessary extensions are properly loaded.\nAre you sure you wish to continue?")) { return; } } setBold(viewPane, UIConstants.ERROR_CONSTANT); setCurrentContentPage(channelEditPanel); setFocus(channelEditTasks); setVisibleTasks(channelEditTasks, channelEditPopupMenu, 0, 4, false); channelEditPanel.editChannel(channel); } /** * Changes the current content page to the Alert Editor with the new alert specified as the * loaded one. */ public void setupAlert(Map<String, Map<String, String>> protocolOptions) { setBold(viewPane, UIConstants.ERROR_CONSTANT); setCurrentContentPage(alertEditPanel); setFocus(alertEditTasks); setVisibleTasks(alertEditTasks, alertEditPopupMenu, 0, 0, false); alertEditPanel.addAlert(protocolOptions); } /** * Edits an alert at a specified index, setting that alert as the current alert in the editor. */ public void editAlert(AlertModel alertModel, Map<String, Map<String, String>> protocolOptions) { if (alertEditPanel.editAlert(alertModel, protocolOptions)) { setBold(viewPane, UIConstants.ERROR_CONSTANT); setCurrentContentPage(alertEditPanel); setFocus(alertEditTasks); setVisibleTasks(alertEditTasks, alertEditPopupMenu, 0, 0, false); } } /** * Edit global scripts */ public void editGlobalScripts() { setBold(viewPane, UIConstants.ERROR_CONSTANT); setCurrentContentPage(globalScriptsPanel); setFocus(globalScriptsTasks); setVisibleTasks(globalScriptsTasks, globalScriptsPopupMenu, 0, 0, false); setPanelName("Global Scripts"); } /** * Sets the current content page to the passed in page. */ public void setCurrentContentPage(Component contentPageObject) { if (contentPageObject == currentContentPage) { return; } if (currentContentPage != null) { contentPane.getViewport().remove(currentContentPage); } contentPane.getViewport().add(contentPageObject); currentContentPage = contentPageObject; // Always cancel the current job if it is still running. if (statusUpdaterJob != null && !statusUpdaterJob.isDone()) { statusUpdaterJob.cancel(true); } // Start a new status updater job if the current content page is the dashboard if (currentContentPage == dashboardPanel || currentContentPage == alertPanel) { statusUpdaterJob = statusUpdaterExecutor.submit(new StatusUpdater()); } } /** * Sets the current task pane container */ private void setCurrentTaskPaneContainer(JXTaskPaneContainer container) { if (container == currentTaskPaneContainer) { return; } if (currentTaskPaneContainer != null) { taskPane.getViewport().remove(currentTaskPaneContainer); } taskPane.getViewport().add(container); currentTaskPaneContainer = container; } /** * Makes all of the task panes and shows the dashboard panel. */ private void makePaneContainer() { createViewPane(); createChannelEditPane(); createDashboardPane(); createEventPane(); createMessagePane(); createUserPane(); createAlertPane(); createAlertEditPane(); createGlobalScriptsPane(); createExtensionsPane(); createOtherPane(); } private void setInitialVisibleTasks() { // View Pane setVisibleTasks(viewPane, null, 0, -1, true); // Alert Pane setVisibleTasks(alertTasks, alertPopupMenu, 0, -1, true); setVisibleTasks(alertTasks, alertPopupMenu, 4, -1, false); // Alert Edit Pane setVisibleTasks(alertEditTasks, alertEditPopupMenu, 0, 0, false); setVisibleTasks(alertEditTasks, alertEditPopupMenu, 1, 1, true); // Channel Edit Pane setVisibleTasks(channelEditTasks, channelEditPopupMenu, 0, 15, false); setVisibleTasks(channelEditTasks, channelEditPopupMenu, 14, 14, true); // Dashboard Pane setVisibleTasks(dashboardTasks, dashboardPopupMenu, 0, 0, true); setVisibleTasks(dashboardTasks, dashboardPopupMenu, 1, -1, false); // Event Pane setVisibleTasks(eventTasks, eventPopupMenu, 0, 2, true); // Message Pane setVisibleTasks(messageTasks, messagePopupMenu, 0, -1, true); setVisibleTasks(messageTasks, messagePopupMenu, 6, -1, false); setVisibleTasks(messageTasks, messagePopupMenu, 7, 7, true); // User Pane setVisibleTasks(userTasks, userPopupMenu, 0, 1, true); setVisibleTasks(userTasks, userPopupMenu, 2, -1, false); // Global Scripts Pane setVisibleTasks(globalScriptsTasks, globalScriptsPopupMenu, 0, 0, false); setVisibleTasks(globalScriptsTasks, globalScriptsPopupMenu, 1, -1, true); // Extensions Pane setVisibleTasks(extensionsTasks, extensionsPopupMenu, 0, 0, true); setVisibleTasks(extensionsTasks, extensionsPopupMenu, 1, -1, false); // Other Pane setVisibleTasks(otherPane, null, 0, -1, true); } /** * Creates the view task pane. */ private void createViewPane() { // Create View pane viewPane = new JXTaskPane(); viewPane.setTitle("Mirth Connect"); viewPane.setName(TaskConstants.VIEW_KEY); viewPane.setFocusable(false); addTask(TaskConstants.VIEW_DASHBOARD, "Dashboard", "Contains information about your currently deployed channels.", "D", new ImageIcon( com.mirth.connect.client.ui.Frame.class.getResource("images/application_view_detail.png")), viewPane, null); addTask(TaskConstants.VIEW_CHANNEL, "Channels", "Contains various operations to perform on your channels.", "C", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/application_form.png")), viewPane, null); addTask(TaskConstants.VIEW_USERS, "Users", "Contains information on users.", "U", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/group.png")), viewPane, null); addTask(TaskConstants.VIEW_SETTINGS, "Settings", "Contains local and system settings.", "S", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/wrench.png")), viewPane, null); addTask(TaskConstants.VIEW_ALERTS, "Alerts", "Contains alert settings.", "A", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/error.png")), viewPane, null); addTask(TaskConstants.VIEW_EVENTS, "Events", "Show the event logs for the system.", "E", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/table.png")), viewPane, null); addTask(TaskConstants.VIEW_EXTENSIONS, "Extensions", "View and manage Mirth Connect extensions", "X", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/plugin.png")), viewPane, null); setNonFocusable(viewPane); taskPaneContainer.add(viewPane); viewPane.setVisible(true); } /** * Creates the template task pane. */ private void createAlertPane() { // Create Alert Edit Tasks Pane alertTasks = new JXTaskPane(); alertPopupMenu = new JPopupMenu(); alertTasks.setTitle("Alert Tasks"); alertTasks.setName(TaskConstants.ALERT_KEY); alertTasks.setFocusable(false); addTask(TaskConstants.ALERT_REFRESH, "Refresh", "Refresh the list of alerts.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/arrow_refresh.png")), alertTasks, alertPopupMenu); addTask(TaskConstants.ALERT_NEW, "New Alert", "Create a new alert.", "N", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/error_add.png")), alertTasks, alertPopupMenu); addTask(TaskConstants.ALERT_IMPORT, "Import Alert", "Import an alert from an XML file.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/report_go.png")), alertTasks, alertPopupMenu); addTask(TaskConstants.ALERT_EXPORT_ALL, "Export All Alerts", "Export all of the alerts to an XML file.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/report_disk.png")), alertTasks, alertPopupMenu); addTask(TaskConstants.ALERT_EXPORT, "Export Alert", "Export the currently selected alert to an XML file.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/report_disk.png")), alertTasks, alertPopupMenu); addTask(TaskConstants.ALERT_DELETE, "Delete Alert", "Delete the currently selected alert.", "L", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/error_delete.png")), alertTasks, alertPopupMenu); addTask(TaskConstants.ALERT_EDIT, "Edit Alert", "Edit the currently selected alert.", "", new ImageIcon( com.mirth.connect.client.ui.Frame.class.getResource("images/application_form_edit.png")), alertTasks, alertPopupMenu); addTask(TaskConstants.ALERT_ENABLE, "Enable Alert", "Enable the currently selected alert.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/control_play_blue.png")), alertTasks, alertPopupMenu); addTask(TaskConstants.ALERT_DISABLE, "Disable Alert", "Disable the currently selected alert.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/control_stop_blue.png")), alertTasks, alertPopupMenu); setNonFocusable(alertTasks); taskPaneContainer.add(alertTasks); } /** * Creates the template task pane. */ private void createAlertEditPane() { // Create Alert Edit Tasks Pane alertEditTasks = new JXTaskPane(); alertEditPopupMenu = new JPopupMenu(); alertEditTasks.setTitle("Alert Edit Tasks"); alertEditTasks.setName(TaskConstants.ALERT_EDIT_KEY); alertEditTasks.setFocusable(false); addTask(TaskConstants.ALERT_EDIT_SAVE, "Save Alert", "Save all changes made to this alert.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/disk.png")), alertEditTasks, alertEditPopupMenu); addTask(TaskConstants.ALERT_EDIT_EXPORT, "Export Alert", "Export the currently selected alert to an XML file.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/report_disk.png")), alertEditTasks, alertEditPopupMenu); setNonFocusable(alertEditTasks); taskPaneContainer.add(alertEditTasks); } /** * Creates the channel edit task pane. */ private void createChannelEditPane() { // Create Channel Edit Tasks Pane channelEditTasks = new JXTaskPane(); channelEditPopupMenu = new JPopupMenu(); channelEditTasks.setTitle("Channel Tasks"); channelEditTasks.setName(TaskConstants.CHANNEL_EDIT_KEY); channelEditTasks.setFocusable(false); addTask(TaskConstants.CHANNEL_EDIT_SAVE, "Save Changes", "Save all changes made to this channel.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/disk.png")), channelEditTasks, channelEditPopupMenu); addTask(TaskConstants.CHANNEL_EDIT_VALIDATE, "Validate Connector", "Validate the currently visible connector.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/accept.png")), channelEditTasks, channelEditPopupMenu); addTask(TaskConstants.CHANNEL_EDIT_NEW_DESTINATION, "New Destination", "Create a new destination.", "N", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/add.png")), channelEditTasks, channelEditPopupMenu); addTask(TaskConstants.CHANNEL_EDIT_DELETE_DESTINATION, "Delete Destination", "Delete the currently selected destination.", "L", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/delete.png")), channelEditTasks, channelEditPopupMenu); addTask(TaskConstants.CHANNEL_EDIT_CLONE_DESTINATION, "Clone Destination", "Clones the currently selected destination.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/page_copy.png")), channelEditTasks, channelEditPopupMenu); addTask(TaskConstants.CHANNEL_EDIT_ENABLE_DESTINATION, "Enable Destination", "Enable the currently selected destination.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/control_play_blue.png")), channelEditTasks, channelEditPopupMenu); addTask(TaskConstants.CHANNEL_EDIT_DISABLE_DESTINATION, "Disable Destination", "Disable the currently selected destination.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/control_stop_blue.png")), channelEditTasks, channelEditPopupMenu); addTask(TaskConstants.CHANNEL_EDIT_MOVE_DESTINATION_UP, "Move Dest. Up", "Move the currently selected destination up.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/arrow_up.png")), channelEditTasks, channelEditPopupMenu); addTask(TaskConstants.CHANNEL_EDIT_MOVE_DESTINATION_DOWN, "Move Dest. Down", "Move the currently selected destination down.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/arrow_down.png")), channelEditTasks, channelEditPopupMenu); addTask(TaskConstants.CHANNEL_EDIT_FILTER, UIConstants.EDIT_FILTER, "Edit the filter for the current connector.", "F", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/table_edit.png")), channelEditTasks, channelEditPopupMenu); addTask(TaskConstants.CHANNEL_EDIT_TRANSFORMER, UIConstants.EDIT_TRANSFORMER, "Edit the transformer for the current connector.", "T", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/table_edit.png")), channelEditTasks, channelEditPopupMenu); addTask(TaskConstants.CHANNEL_EDIT_RESPONSE_TRANSFORMER, UIConstants.EDIT_RESPONSE_TRANSFORMER, "Edit the response transformer for the current connector.", "R", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/table_edit.png")), channelEditTasks, channelEditPopupMenu); addTask(TaskConstants.CHANNEL_EDIT_IMPORT_CONNECTOR, "Import Connector", "Import the currently displayed connector from an XML file.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/report_go.png")), channelEditTasks, channelEditPopupMenu); addTask(TaskConstants.CHANNEL_EDIT_EXPORT_CONNECTOR, "Export Connector", "Export the currently displayed connector to an XML file.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/report_disk.png")), channelEditTasks, channelEditPopupMenu); addTask(TaskConstants.CHANNEL_EDIT_EXPORT, "Export Channel", "Export the currently selected channel to an XML file.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/report_disk.png")), channelEditTasks, channelEditPopupMenu); addTask(TaskConstants.CHANNEL_EDIT_VALIDATE_SCRIPT, "Validate Script", "Validate the currently viewed script.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/accept.png")), channelEditTasks, channelEditPopupMenu); addTask(TaskConstants.CHANNEL_EDIT_DEPLOY, "Deploy Channel", "Deploy the currently selected channel.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/arrow_redo.png")), channelEditTasks, channelEditPopupMenu); setNonFocusable(channelEditTasks); taskPaneContainer.add(channelEditTasks); } /** * Creates the status task pane. */ private void createDashboardPane() { // Create Status Tasks Pane dashboardTasks = new JXTaskPane(); dashboardPopupMenu = new JPopupMenu(); dashboardTasks.setTitle("Dashboard Tasks"); dashboardTasks.setName(TaskConstants.DASHBOARD_KEY); dashboardTasks.setFocusable(false); addTask(TaskConstants.DASHBOARD_REFRESH, "Refresh", "Refresh the list of statuses.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/arrow_refresh.png")), dashboardTasks, dashboardPopupMenu); addTask(TaskConstants.DASHBOARD_SEND_MESSAGE, "Send Message", "Send messages to the currently selected channel.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/email_go.png")), dashboardTasks, dashboardPopupMenu); addTask(TaskConstants.DASHBOARD_SHOW_MESSAGES, "View Messages", "Show the messages for the currently selected channel.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/page_white_stack.png")), dashboardTasks, dashboardPopupMenu); addTask(TaskConstants.DASHBOARD_REMOVE_ALL_MESSAGES, "Remove All Messages", "Remove all Messages in this channel.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/email_delete.png")), dashboardTasks, dashboardPopupMenu); addTask(TaskConstants.DASHBOARD_CLEAR_STATS, "Clear Statistics", "Reset the statistics for this channel.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/chart_bar_delete.png")), dashboardTasks, dashboardPopupMenu); addTask(TaskConstants.DASHBOARD_START, "Start", "Start the currently selected channel.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/control_play_blue.png")), dashboardTasks, dashboardPopupMenu); addTask(TaskConstants.DASHBOARD_PAUSE, "Pause", "Pause the currently selected channel.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/control_pause_blue.png")), dashboardTasks, dashboardPopupMenu); addTask(TaskConstants.DASHBOARD_STOP, "Stop", "Stop the currently selected channel.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/control_stop_blue.png")), dashboardTasks, dashboardPopupMenu); addTask(TaskConstants.DASHBOARD_HALT, "Halt", "Halt the currently selected channel.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/stop.png")), dashboardTasks, dashboardPopupMenu); addTask(TaskConstants.DASHBOARD_UNDEPLOY, "Undeploy Channel", "Undeploys the currently selected channel.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/arrow_undo.png")), dashboardTasks, dashboardPopupMenu); addTask(TaskConstants.DASHBOARD_START_CONNECTOR, "Start", "Start the currently selected connector.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/control_play_blue.png")), dashboardTasks, dashboardPopupMenu); addTask(TaskConstants.DASHBOARD_STOP_CONNECTOR, "Stop", "Stop the currently selected connector.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/control_stop_blue.png")), dashboardTasks, dashboardPopupMenu); setNonFocusable(dashboardTasks); taskPaneContainer.add(dashboardTasks); } /** * Creates the event task pane. */ private void createEventPane() { // Create Event Tasks Pane eventTasks = new JXTaskPane(); eventPopupMenu = new JPopupMenu(); eventTasks.setTitle("Event Tasks"); eventTasks.setName(TaskConstants.EVENT_KEY); eventTasks.setFocusable(false); addTask(TaskConstants.EVENT_REFRESH, "Refresh", "Refresh the list of events with the given filter.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/arrow_refresh.png")), eventTasks, eventPopupMenu); addTask(TaskConstants.EVENT_EXPORT_ALL, "Export All Events", "Export all events to a file on the server.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/report_disk.png")), eventTasks, eventPopupMenu); addTask(TaskConstants.EVENT_REMOVE_ALL, "Remove All Events", "Remove all events and optionally export them to a file on the server.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/table_delete.png")), eventTasks, eventPopupMenu); setNonFocusable(eventTasks); taskPaneContainer.add(eventTasks); } /** * Creates the message task pane. */ private void createMessagePane() { // Create Message Tasks Pane messageTasks = new JXTaskPane(); messagePopupMenu = new JPopupMenu(); messageTasks.setTitle("Message Tasks"); messageTasks.setName(TaskConstants.MESSAGE_KEY); messageTasks.setFocusable(false); addTask(TaskConstants.MESSAGE_REFRESH, "Refresh", "Refresh the list of messages with the current search criteria.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/arrow_refresh.png")), messageTasks, messagePopupMenu); addTask(TaskConstants.MESSAGE_SEND, "Send Message", "Send a message to the channel.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/email_go.png")), messageTasks, messagePopupMenu); addTask(TaskConstants.MESSAGE_IMPORT, "Import Messages", "Import messages from a file.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/report_go.png")), messageTasks, messagePopupMenu); addTask(TaskConstants.MESSAGE_EXPORT, "Export Results", "Export all messages in the current search.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/report_disk.png")), messageTasks, messagePopupMenu); addTask(TaskConstants.MESSAGE_REMOVE_ALL, "Remove All Messages", "Remove all messages in this channel.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/email_delete.png")), messageTasks, messagePopupMenu); addTask(TaskConstants.MESSAGE_REMOVE_FILTERED, "Remove Results", "Remove all messages in the current search.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/email_delete.png")), messageTasks, messagePopupMenu); addTask(TaskConstants.MESSAGE_REMOVE, "Remove Message", "Remove the selected Message.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/delete.png")), messageTasks, messagePopupMenu); addTask(TaskConstants.MESSAGE_REPROCESS_FILTERED, "Reprocess Results", "Reprocess all messages in the current search.", "", new ImageIcon( com.mirth.connect.client.ui.Frame.class.getResource("images/arrow_rotate_clockwise.png")), messageTasks, messagePopupMenu); addTask(TaskConstants.MESSAGE_REPROCESS, "Reprocess Message", "Reprocess the selected message.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/arrow_redo.png")), messageTasks, messagePopupMenu); addTask(TaskConstants.MESSAGE_VIEW_IMAGE, "View Attachment", "View Attachment", "View the attachment for the selected message.", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/attach.png")), messageTasks, messagePopupMenu); addTask(TaskConstants.MESSAGE_EXPORT_ATTACHMENT, "Export Attachment", "Export Attachment", "Export the selected attachment to a file.", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/report_disk.png")), messageTasks, messagePopupMenu); setNonFocusable(messageTasks); taskPaneContainer.add(messageTasks); } /** * Creates the users task pane. */ private void createUserPane() { // Create User Tasks Pane userTasks = new JXTaskPane(); userPopupMenu = new JPopupMenu(); userTasks.setTitle("User Tasks"); userTasks.setName(TaskConstants.USER_KEY); userTasks.setFocusable(false); addTask(TaskConstants.USER_REFRESH, "Refresh", "Refresh the list of users.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/arrow_refresh.png")), userTasks, userPopupMenu); addTask(TaskConstants.USER_NEW, "New User", "Create a new user.", "N", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/user_add.png")), userTasks, userPopupMenu); addTask(TaskConstants.USER_EDIT, "Edit User", "Edit the currently selected user.", "I", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/user_edit.png")), userTasks, userPopupMenu); addTask(TaskConstants.USER_DELETE, "Delete User", "Delete the currently selected user.", "L", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/user_delete.png")), userTasks, userPopupMenu); setNonFocusable(userTasks); taskPaneContainer.add(userTasks); } /** * Creates the global scripts edit task pane. */ private void createGlobalScriptsPane() { globalScriptsTasks = new JXTaskPane(); globalScriptsPopupMenu = new JPopupMenu(); globalScriptsTasks.setTitle("Script Tasks"); globalScriptsTasks.setName(TaskConstants.GLOBAL_SCRIPT_KEY); globalScriptsTasks.setFocusable(false); addTask(TaskConstants.GLOBAL_SCRIPT_SAVE, "Save Scripts", "Save all changes made to all scripts.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/disk.png")), globalScriptsTasks, globalScriptsPopupMenu); addTask(TaskConstants.GLOBAL_SCRIPT_VALIDATE, "Validate Script", "Validate the currently viewed script.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/accept.png")), globalScriptsTasks, globalScriptsPopupMenu); addTask(TaskConstants.GLOBAL_SCRIPT_IMPORT, "Import Scripts", "Import all global scripts from an XML file.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/report_go.png")), globalScriptsTasks, globalScriptsPopupMenu); addTask(TaskConstants.GLOBAL_SCRIPT_EXPORT, "Export Scripts", "Export all global scripts to an XML file.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/report_disk.png")), globalScriptsTasks, globalScriptsPopupMenu); setNonFocusable(globalScriptsTasks); taskPaneContainer.add(globalScriptsTasks); } /** * Creates the extensions task pane. */ private void createExtensionsPane() { extensionsTasks = new JXTaskPane(); extensionsPopupMenu = new JPopupMenu(); extensionsTasks.setTitle("Extension Tasks"); extensionsTasks.setName(TaskConstants.EXTENSIONS_KEY); extensionsTasks.setFocusable(false); addTask(TaskConstants.EXTENSIONS_REFRESH, "Refresh", "Refresh loaded plugins.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/arrow_refresh.png")), extensionsTasks, extensionsPopupMenu); addTask(TaskConstants.EXTENSIONS_ENABLE, "Enable Extension", "Enable the currently selected extension.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/control_play_blue.png")), extensionsTasks, extensionsPopupMenu); addTask(TaskConstants.EXTENSIONS_DISABLE, "Disable Extension", "Disable the currently selected extension.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/control_stop_blue.png")), extensionsTasks, extensionsPopupMenu); addTask(TaskConstants.EXTENSIONS_SHOW_PROPERTIES, "Show Properties", "Display the currently selected extension properties.", "", new ImageIcon( com.mirth.connect.client.ui.Frame.class.getResource("images/application_view_list.png")), extensionsTasks, extensionsPopupMenu); addTask(TaskConstants.EXTENSIONS_UNINSTALL, "Uninstall Extension", "Uninstall the currently selected extension", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/plugin_delete.png")), extensionsTasks, extensionsPopupMenu); setNonFocusable(extensionsTasks); taskPaneContainer.add(extensionsTasks); } /** * Creates the other task pane. */ private void createOtherPane() { // Create Other Pane otherPane = new JXTaskPane(); otherPane.setTitle("Other"); otherPane.setName(TaskConstants.OTHER_KEY); otherPane.setFocusable(false); addTask(TaskConstants.OTHER_NOTIFICATIONS, UIConstants.VIEW_NOTIFICATIONS, "View notifications from Mirth.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/flag_orange.png")), otherPane, null); addTask(TaskConstants.OTHER_VIEW_USER_API, "View User API", "View documentation for the Mirth Connect User API.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/page_white_text.png")), otherPane, null); addTask(TaskConstants.OTHER_VIEW_CLIENT_API, "View Client API", "View documentation for the Mirth Connect Client API.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/page_white_text.png")), otherPane, null); addTask(TaskConstants.OTHER_HELP, "Help", "View the Mirth Connect wiki.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/help.png")), otherPane, null); addTask(TaskConstants.OTHER_ABOUT, "About Mirth Connect", "View the about page for Mirth Connect.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/information.png")), otherPane, null); addTask(TaskConstants.OTHER_VISIT_MIRTH, "Visit mirthcorp.com", "View Mirth's homepage.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/house.png")), otherPane, null); addTask(TaskConstants.OTHER_REPORT_ISSUE, "Report Issue", "Visit Mirth's issue tracker.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/bug.png")), otherPane, null); addTask(TaskConstants.OTHER_LOGOUT, "Logout", "Logout and return to the login screen.", "", new ImageIcon(com.mirth.connect.client.ui.Frame.class.getResource("images/disconnect.png")), otherPane, null); setNonFocusable(otherPane); taskPaneContainer.add(otherPane); otherPane.setVisible(true); } public JXTaskPane getOtherPane() { return otherPane; } public void updateNotificationTaskName(int notifications) { String taskName = UIConstants.VIEW_NOTIFICATIONS; if (notifications > 0) { taskName += " (" + notifications + ")"; } ((JXHyperlink) otherPane.getContentPane().getComponent(UIConstants.VIEW_NOTIFICATIONS_TASK_NUMBER)) .setText(taskName); } public int addTask(String callbackMethod, String displayName, String toolTip, String shortcutKey, ImageIcon icon, JXTaskPane pane, JPopupMenu menu) { return addTask(callbackMethod, displayName, toolTip, shortcutKey, icon, pane, menu, this); } /** * Initializes the bound method call for the task pane actions and adds them to the * taskpane/popupmenu. */ public int addTask(String callbackMethod, String displayName, String toolTip, String shortcutKey, ImageIcon icon, JXTaskPane pane, JPopupMenu menu, Object handler) { BoundAction boundAction = ActionFactory.createBoundAction(callbackMethod, displayName, shortcutKey); if (icon != null) { boundAction.putValue(Action.SMALL_ICON, icon); } boundAction.putValue(Action.SHORT_DESCRIPTION, toolTip); boundAction.registerCallback(handler, callbackMethod); Component component = pane.add(boundAction); getComponentTaskMap().put(component, callbackMethod); if (menu != null) { menu.add(boundAction); } return (pane.getContentPane().getComponentCount() - 1); } public Map<Component, String> getComponentTaskMap() { return componentTaskMap; } /** * Alerts the user with a yes/no option with the passed in 'message' */ public boolean alertOption(Component parentComponent, String message) { int option = JOptionPane.showConfirmDialog(getVisibleComponent(parentComponent), message, "Select an Option", JOptionPane.YES_NO_OPTION); if (option == JOptionPane.YES_OPTION) { return true; } else { return false; } } /** * Alerts the user with a Ok/cancel option with the passed in 'message' */ public boolean alertOkCancel(Component parentComponent, String message) { int option = JOptionPane.showConfirmDialog(getVisibleComponent(parentComponent), message, "Select an Option", JOptionPane.OK_CANCEL_OPTION); if (option == JOptionPane.OK_OPTION) { return true; } else { return false; } } public enum ConflictOption { YES, YES_APPLY_ALL, NO, NO_APPLY_ALL; } /** * Alerts the user with a conflict resolution dialog */ public ConflictOption alertConflict(Component parentComponent, String message, int count) { final JCheckBox conflictCheckbox = new JCheckBox( "Do this for the next " + String.valueOf(count - 1) + " conflicts"); conflictCheckbox.setSelected(false); Object[] params = { message, conflictCheckbox }; int jOption = JOptionPane.showConfirmDialog(getVisibleComponent(parentComponent), params, "Select an Option", JOptionPane.YES_NO_OPTION); boolean isSelected = conflictCheckbox.isSelected(); ConflictOption conflictOption = null; if (jOption == JOptionPane.YES_OPTION) { if (isSelected) { conflictOption = ConflictOption.YES_APPLY_ALL; } else { conflictOption = ConflictOption.YES; } } else { if (isSelected || jOption == -1) { conflictOption = ConflictOption.NO_APPLY_ALL; } else { conflictOption = ConflictOption.NO; } } return conflictOption; } public boolean alertRefresh() { boolean cancelRefresh = false; if (PlatformUI.MIRTH_FRAME.isSaveEnabled()) { int option = JOptionPane.showConfirmDialog(PlatformUI.MIRTH_FRAME, "<html>Any unsaved changes will be lost.<br>Would you like to continue?</html>", "Warning", JOptionPane.YES_NO_OPTION); if (option == JOptionPane.NO_OPTION || option == JOptionPane.CLOSED_OPTION) { cancelRefresh = true; } else { setSaveEnabled(false); } } return cancelRefresh; } /** * Alerts the user with an information dialog with the passed in 'message' */ public void alertInformation(Component parentComponent, String message) { JOptionPane.showMessageDialog(getVisibleComponent(parentComponent), message, "Information", JOptionPane.INFORMATION_MESSAGE); } /** * Alerts the user with a warning dialog with the passed in 'message' */ public void alertWarning(Component parentComponent, String message) { JOptionPane.showMessageDialog(getVisibleComponent(parentComponent), message, "Warning", JOptionPane.WARNING_MESSAGE); } /** * Alerts the user with an error dialog with the passed in 'message' */ public void alertError(Component parentComponent, String message) { JOptionPane.showMessageDialog(getVisibleComponent(parentComponent), message, "Error", JOptionPane.ERROR_MESSAGE); } /** * Alerts the user with an error dialog with the passed in 'message' and a 'question'. */ public void alertCustomError(Component parentComponent, String message, String question) { parentComponent = getVisibleComponent(parentComponent); Window owner = getWindowForComponent(parentComponent); if (owner instanceof java.awt.Frame) { new CustomErrorDialog((java.awt.Frame) owner, message, question); } else { // window instanceof Dialog new CustomErrorDialog((java.awt.Dialog) owner, message, question); } } /** * Alerts the user with an exception dialog with the passed in stack trace. */ public void alertThrowable(Component parentComponent, Throwable t) { alertThrowable(parentComponent, t, null); } /** * Alerts the user with an exception dialog with the passed in stack trace. */ public void alertThrowable(Component parentComponent, Throwable t, String customMessage) { alertThrowable(parentComponent, t, customMessage, true); } /** * Alerts the user with an exception dialog with the passed in stack trace. */ public void alertThrowable(Component parentComponent, Throwable t, boolean showMessageOnForbidden) { alertThrowable(parentComponent, t, null, showMessageOnForbidden); } /** * Alerts the user with an exception dialog with the passed in stack trace. */ public void alertThrowable(Component parentComponent, Throwable t, String customMessage, boolean showMessageOnForbidden) { alertThrowable(parentComponent, t, customMessage, showMessageOnForbidden, null); } /** * Alerts the user with an exception dialog with the passed in stack trace. */ public void alertThrowable(Component parentComponent, Throwable t, String customMessage, String safeErrorKey) { alertThrowable(parentComponent, t, customMessage, true, safeErrorKey); } /** * Alerts the user with an exception dialog with the passed in stack trace. */ public void alertThrowable(Component parentComponent, Throwable t, String customMessage, boolean showMessageOnForbidden, String safeErrorKey) { if (connectionError) { return; } if (safeErrorKey != null) { increaseSafeErrorFailCount(safeErrorKey); if (getSafeErrorFailCount(safeErrorKey) < 3) { return; } } parentComponent = getVisibleComponent(parentComponent); String message = StringUtils.trimToEmpty(customMessage); boolean showDialog = true; if (t != null) { // Always print the stacktrace for troubleshooting purposes t.printStackTrace(); if (t instanceof ExecutionException && t.getCause() != null) { t = t.getCause(); } if (t.getCause() != null && t.getCause() instanceof ClientException) { t = t.getCause(); } if (StringUtils.isBlank(message) && StringUtils.isNotBlank(t.getMessage())) { message = t.getMessage(); } /* * Logout if an exception occurs that indicates the server is no longer running or * accessible. We only want to do this if a ClientException was passed in, indicating it * was actually due to a request to the server. Other places in the application could * call this method with an exception that happens to contain the string * "Connection reset", for example. */ if (t instanceof ClientException) { if (t instanceof ForbiddenException || t.getCause() != null && t.getCause() instanceof ForbiddenException) { message = "You are not authorized to perform this action.\n\n" + message; if (!showMessageOnForbidden) { showDialog = false; } } else if (StringUtils.contains(t.getMessage(), "Received close_notify during handshake")) { return; } else if (t.getCause() != null && t.getCause() instanceof IllegalStateException && mirthClient.isClosed()) { return; } else if (StringUtils.contains(t.getMessage(), "reset") || (t instanceof UnauthorizedException || t.getCause() != null && t.getCause() instanceof UnauthorizedException)) { connectionError = true; statusUpdaterExecutor.shutdownNow(); alertWarning(parentComponent, "Sorry your connection to Mirth has either timed out or there was an error in the connection. Please login again."); if (!exportChannelOnError()) { return; } mirthClient.close(); this.dispose(); LoginPanel.getInstance().initialize(PlatformUI.SERVER_URL, PlatformUI.CLIENT_VERSION, "", ""); return; } else if (t.getCause() != null && t.getCause() instanceof HttpHostConnectException && StringUtils.contains(t.getCause().getMessage(), "Connection refused")) { connectionError = true; statusUpdaterExecutor.shutdownNow(); String server; if (!StringUtils.isBlank(PlatformUI.SERVER_NAME)) { server = PlatformUI.SERVER_NAME + "(" + PlatformUI.SERVER_URL + ")"; } else { server = PlatformUI.SERVER_URL; } alertWarning(parentComponent, "The Mirth Connect server " + server + " is no longer running. Please start it and log in again."); if (!exportChannelOnError()) { return; } mirthClient.close(); this.dispose(); LoginPanel.getInstance().initialize(PlatformUI.SERVER_URL, PlatformUI.CLIENT_VERSION, "", ""); return; } } for (String stackFrame : ExceptionUtils.getStackFrames(t)) { if (StringUtils.isNotEmpty(message)) { message += '\n'; } message += StringUtils.trim(stackFrame); } } logger.error(message); if (showDialog) { Window owner = getWindowForComponent(parentComponent); if (owner instanceof java.awt.Frame) { new ErrorDialog((java.awt.Frame) owner, message); } else { // window instanceof Dialog new ErrorDialog((java.awt.Dialog) owner, message); } } } private Component getVisibleComponent(Component component) { if (component != null && component.isVisible()) { return component; } else if (this.isVisible()) { return this; } else { return null; } } private Window getWindowForComponent(Component parentComponent) { Window owner = null; if (parentComponent == null) { owner = this; } else if (parentComponent instanceof java.awt.Frame || parentComponent instanceof java.awt.Dialog) { owner = (Window) parentComponent; } else { owner = SwingUtilities.windowForComponent(parentComponent); if (owner == null) { owner = this; } } return owner; } /** * Sets the 'index' in 'pane' to be bold */ public void setBold(JXTaskPane pane, int index) { for (int i = 0; i < pane.getContentPane().getComponentCount(); i++) { pane.getContentPane().getComponent(i).setFont(UIConstants.TEXTFIELD_PLAIN_FONT); } if (index != UIConstants.ERROR_CONSTANT) { pane.getContentPane().getComponent(index).setFont(UIConstants.TEXTFIELD_BOLD_FONT); } } /** * Sets the visible task pane to the specified 'pane' */ public void setFocus(JXTaskPane pane) { setFocus(new JXTaskPane[] { pane }, true, true); } /** * Sets the visible task panes to the specified 'panes'. Also allows setting the 'Mirth' and * 'Other' panes. */ public void setFocus(JXTaskPane[] panes, boolean mirthPane, boolean otherPane) { taskPaneContainer.getComponent(0).setVisible(mirthPane); // ignore the first and last components for (int i = 1; i < taskPaneContainer.getComponentCount() - 1; i++) { taskPaneContainer.getComponent(i).setVisible(false); } taskPaneContainer.getComponent(taskPaneContainer.getComponentCount() - 1).setVisible(otherPane); if (panes != null) { for (JXTaskPane pane : panes) { if (pane != null) { pane.setVisible(true); } } } } /** * Sets all components in pane to be non-focusable. */ public void setNonFocusable(JXTaskPane pane) { for (int i = 0; i < pane.getContentPane().getComponentCount(); i++) { pane.getContentPane().getComponent(i).setFocusable(false); } } /** * Sets the visible tasks in the given 'pane' and 'menu'. The method takes an interval of * indices (end index should be -1 to go to the end), as well as a whether they should be set to * visible or not-visible. */ public void setVisibleTasks(JXTaskPane pane, JPopupMenu menu, int startIndex, int endIndex, boolean visible) { // If the endIndex is -1, disregard it, otherwise stop there. for (int i = startIndex; (endIndex == -1 ? true : i <= endIndex) && (i < pane.getContentPane().getComponentCount()); i++) { // If the component being set visible is in the security list, don't allow it. boolean componentVisible = visible; String componentTask = getComponentTaskMap().get(pane.getContentPane().getComponent(i)); if (componentTask != null) { if (!AuthorizationControllerFactory.getAuthorizationController().checkTask(pane.getName(), componentTask)) { componentVisible = false; } } pane.getContentPane().getComponent(i).setVisible(componentVisible); if (menu != null) { menu.getComponent(i).setVisible(componentVisible); } } } /** * A prompt to ask the user if he would like to save the changes made before leaving the page. */ public boolean confirmLeave() { if (currentContentPage == channelPanel && isSaveEnabled()) { if (!channelPanel.confirmLeave()) { return false; } } else if ((currentContentPage == channelEditPanel || currentContentPage == channelEditPanel.transformerPane || currentContentPage == channelEditPanel.filterPane) && isSaveEnabled()) { int option = JOptionPane.showConfirmDialog(this, "Would you like to save the channel changes?"); if (option == JOptionPane.YES_OPTION) { if (!channelEditPanel.saveChanges()) { return false; } } else if (option == JOptionPane.CANCEL_OPTION || option == JOptionPane.CLOSED_OPTION) { return false; } } else if (currentContentPage == settingsPane && isSaveEnabled()) { int option = JOptionPane.showConfirmDialog(this, "Would you like to save the " + settingsPane.getCurrentSettingsPanel().getTabName() + " settings changes?"); if (option == JOptionPane.YES_OPTION) { if (!settingsPane.getCurrentSettingsPanel().doSave()) { return false; } } else if (option == JOptionPane.CANCEL_OPTION || option == JOptionPane.CLOSED_OPTION) { return false; } } else if (currentContentPage == alertEditPanel && isSaveEnabled()) { int option = JOptionPane.showConfirmDialog(this, "Would you like to save the alerts?"); if (option == JOptionPane.YES_OPTION) { if (!alertEditPanel.saveAlert()) { return false; } } else if (option == JOptionPane.CANCEL_OPTION || option == JOptionPane.CLOSED_OPTION) { return false; } } else if (currentContentPage == globalScriptsPanel && isSaveEnabled()) { int option = JOptionPane.showConfirmDialog(this, "Would you like to save the scripts?"); if (option == JOptionPane.YES_OPTION) { if (!doSaveGlobalScripts()) { return false; } } else if (option == JOptionPane.CANCEL_OPTION || option == JOptionPane.CLOSED_OPTION) { return false; } } else if (currentContentPage == codeTemplatePanel && isSaveEnabled()) { if (!codeTemplatePanel.confirmLeave()) { return false; } } setSaveEnabled(false); return true; } /** * Sends the channel passed in to the server, updating it or adding it. * * @throws ClientException */ public boolean updateChannel(Channel curr, boolean overwriting) throws ClientException { if (overwriting ? !mirthClient.updateChannel(curr, false) : !mirthClient.createChannel(curr)) { if (alertOption(this, "This channel has been modified since you first opened it.\nWould you like to overwrite it?")) { mirthClient.updateChannel(curr, true); } else { return false; } } channelPanel.retrieveChannels(); return true; } /** * Sends the passed in user to the server, updating it or adding it. */ public boolean updateUser(final Component parentComponent, final User updateUser, final String newPassword) { final String workingId = startWorking("Saving user..."); try { if (StringUtils.isNotEmpty(newPassword)) { /* * If a new user is being passed in (null user id), the password will only be * checked right now. */ if (!checkOrUpdateUserPassword(parentComponent, updateUser, newPassword)) { return false; } } try { if (updateUser.getId() == null) { mirthClient.createUser(updateUser); } else { mirthClient.updateUser(updateUser); } } catch (ClientException e) { if (e.getMessage() != null && e.getMessage().contains("username must be unique")) { alertWarning(parentComponent, "This username already exists. Please choose another one."); } else { alertThrowable(parentComponent, e); } return false; } try { retrieveUsers(); /* * If the user id was null, a new user was being created and the password was only * checked. Get the created user with the id and then update the password. */ if (updateUser.getId() == null) { User newUser = null; for (User user : users) { if (user.getUsername().equals(updateUser.getUsername())) { newUser = user; } } checkOrUpdateUserPassword(parentComponent, newUser, newPassword); } } catch (ClientException e) { alertThrowable(parentComponent, e); } finally { // The userPanel will be null if the user panel has not been viewed (i.e. registration). if (userPanel != null) { userPanel.updateUserTable(); } } } finally { stopWorking(workingId); } return true; } /** * If the current user is being updated, it needs to be done in the main thread so that the * username can be changed, re-logged in, and the current user information can be updated. * * @param parentComponent * @param currentUser * @param newPassword * @return */ public boolean updateCurrentUser(Component parentComponent, final User currentUser, String newPassword) { // Find out if the username is being changed so that we can login again. boolean changingUsername = !currentUser.getUsername().equals(PlatformUI.USER_NAME); final String workingId = startWorking("Saving user..."); try { /* * If there is a new password, update it. If not, make sure that the username is not * being changed, since the password must be updated when the username is changed. */ if (StringUtils.isNotEmpty(newPassword)) { if (!checkOrUpdateUserPassword(parentComponent, currentUser, newPassword)) { return false; } } else if (changingUsername) { alertWarning(parentComponent, "If you are changing your username, you must also update your password."); return false; } try { mirthClient.updateUser(currentUser); } catch (ClientException e) { if (e.getMessage() != null && e.getMessage().contains("username must be unique")) { alertWarning(parentComponent, "This username already exists. Please choose another one."); } else { alertThrowable(parentComponent, e); } return false; } try { retrieveUsers(); } catch (ClientException e) { alertThrowable(parentComponent, e); } finally { // The userPanel will be null if the user panel has not been viewed (i.e. registration). if (userPanel != null) { userPanel.updateUserTable(); } } } finally { stopWorking(workingId); } // If the username is being changed, login again. if (changingUsername) { final String workingId2 = startWorking("Switching User..."); try { LoadedExtensions.getInstance().resetPlugins(); mirthClient.logout(); mirthClient.login(currentUser.getUsername(), newPassword); PlatformUI.USER_NAME = currentUser.getUsername(); } catch (ClientException e) { alertThrowable(parentComponent, e); } finally { stopWorking(workingId2); } } return true; } public boolean checkOrUpdateUserPassword(Component parentComponent, final User currentUser, String newPassword) { try { List<String> responses; if (currentUser.getId() == null) { responses = mirthClient.checkUserPassword(newPassword); } else { responses = mirthClient.updateUserPassword(currentUser.getId(), newPassword); } if (CollectionUtils.isNotEmpty(responses)) { String responseString = "Your password is not valid. Please fix the following:\n"; for (String response : responses) { responseString += (" - " + response + "\n"); } alertError(this, responseString); return false; } } catch (ClientException e) { alertThrowable(this, e); return false; } return true; } public User getCurrentUser(Component parentComponent) { User currentUser = null; try { retrieveUsers(); for (User user : users) { if (user.getUsername().equals(PlatformUI.USER_NAME)) { currentUser = user; } } } catch (ClientException e) { alertThrowable(parentComponent, e); } return currentUser; } public void registerUser(final User user) { final String workingId = startWorking("Registering user..."); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { public Void doInBackground() { try { ConnectServiceUtil.registerUser(PlatformUI.SERVER_ID, PlatformUI.SERVER_VERSION, user, PlatformUI.HTTPS_PROTOCOLS, PlatformUI.HTTPS_CIPHER_SUITES); } catch (ClientException e) { // ignore errors connecting to update/stats server } return null; } public void done() { stopWorking(workingId); } }; worker.execute(); } public void sendUsageStatistics() { UpdateSettings updateSettings = null; try { updateSettings = mirthClient.getUpdateSettings(); } catch (Exception e) { } if (updateSettings != null && updateSettings.getStatsEnabled()) { final String workingId = startWorking("Sending usage statistics..."); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { public Void doInBackground() { try { String usageData = mirthClient.getUsageData(getClientStats()); if (usageData != null) { boolean isSent = ConnectServiceUtil.sendStatistics(PlatformUI.SERVER_ID, PlatformUI.SERVER_VERSION, false, usageData, PlatformUI.HTTPS_PROTOCOLS, PlatformUI.HTTPS_CIPHER_SUITES); if (isSent) { UpdateSettings settings = new UpdateSettings(); settings.setLastStatsTime(System.currentTimeMillis()); mirthClient.setUpdateSettings(settings); } } } catch (ClientException e) { // ignore errors connecting to update/stats server } return null; } public void done() { stopWorking(workingId); } }; worker.execute(); } } private Map<String, Object> getClientStats() { Map<String, Object> clientStats = new HashMap<String, Object>(); clientStats.put("javaVersion", System.getProperty("java.version")); return clientStats; } /** * Enables the save button for needed page. */ public void setSaveEnabled(boolean enabled) { if (currentContentPage == channelPanel) { channelPanel.setSaveEnabled(enabled); } else if (currentContentPage == channelEditPanel) { setVisibleTasks(channelEditTasks, channelEditPopupMenu, 0, 0, enabled); } else if (channelEditPanel != null && currentContentPage == channelEditPanel.transformerPane) { channelEditPanel.transformerPane.modified = enabled; } else if (channelEditPanel != null && currentContentPage == channelEditPanel.filterPane) { channelEditPanel.filterPane.modified = enabled; } else if (currentContentPage == settingsPane) { settingsPane.getCurrentSettingsPanel().setSaveEnabled(enabled); } else if (alertEditPanel != null && currentContentPage == alertEditPanel) { setVisibleTasks(alertEditTasks, alertEditPopupMenu, 0, 0, enabled); } else if (globalScriptsPanel != null && currentContentPage == globalScriptsPanel) { setVisibleTasks(globalScriptsTasks, globalScriptsPopupMenu, 0, 0, enabled); } else if (currentContentPage == codeTemplatePanel) { codeTemplatePanel.setSaveEnabled(enabled); } } /** * Enables the save button for needed page. */ public boolean isSaveEnabled() { boolean enabled = false; if (currentContentPage != null) { if (currentContentPage == channelPanel) { enabled = channelPanel.isSaveEnabled(); } else if (currentContentPage == channelEditPanel) { enabled = channelEditTasks.getContentPane().getComponent(0).isVisible(); } else if (channelEditPanel != null && currentContentPage == channelEditPanel.transformerPane) { enabled = channelEditTasks.getContentPane().getComponent(0).isVisible() || channelEditPanel.transformerPane.modified; } else if (channelEditPanel != null && currentContentPage == channelEditPanel.filterPane) { enabled = channelEditTasks.getContentPane().getComponent(0).isVisible() || channelEditPanel.filterPane.modified; } else if (currentContentPage == settingsPane) { enabled = settingsPane.getCurrentSettingsPanel().isSaveEnabled(); } else if (alertEditPanel != null && currentContentPage == alertEditPanel) { enabled = alertEditTasks.getContentPane().getComponent(0).isVisible(); } else if (globalScriptsPanel != null && currentContentPage == globalScriptsPanel) { enabled = globalScriptsTasks.getContentPane().getComponent(0).isVisible(); } else if (currentContentPage == codeTemplatePanel) { enabled = codeTemplatePanel.isSaveEnabled(); } } return enabled; } // //////////////////////////////////////////////////////////// // --- All bound actions are beneath this point --- // // //////////////////////////////////////////////////////////// public void goToMirth() { BareBonesBrowserLaunch.openURL("http://www.mirthcorp.com/"); } public void goToUserAPI() { BareBonesBrowserLaunch.openURL(PlatformUI.SERVER_URL + UIConstants.USER_API_LOCATION); } public void goToClientAPI() { BareBonesBrowserLaunch.openURL(PlatformUI.SERVER_URL + UIConstants.CLIENT_API_LOCATION); } public void goToAbout() { new AboutMirth(); } public void doReportIssue() { BareBonesBrowserLaunch.openURL(UIConstants.ISSUE_TRACKER_LOCATION); } public void doShowDashboard() { if (dashboardPanel == null) { dashboardPanel = new DashboardPanel(); } if (!confirmLeave()) { return; } dashboardPanel.switchPanel(); setBold(viewPane, 0); setPanelName("Dashboard"); setCurrentContentPage(dashboardPanel); setFocus(dashboardTasks); doRefreshStatuses(true); } public void doShowChannel() { if (!confirmLeave()) { return; } channelPanel.switchPanel(); } public void doShowUsers() { if (userPanel == null) { userPanel = new UserPanel(); } if (!confirmLeave()) { return; } final String workingId = startWorking("Loading users..."); setBold(viewPane, 2); setPanelName("Users"); setCurrentContentPage(userPanel); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { public Void doInBackground() { refreshUser(); return null; } public void done() { setFocus(userTasks); stopWorking(workingId); } }; worker.execute(); } public void doShowSettings() { if (settingsPane == null) { settingsPane = new SettingsPane(); } if (!confirmLeave()) { return; } final String workingId = startWorking("Loading settings..."); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { public Void doInBackground() { settingsPane.setSelectedSettingsPanel(0); return null; } public void done() { setBold(viewPane, 3); setPanelName("Settings"); setCurrentContentPage(settingsPane); stopWorking(workingId); } }; worker.execute(); } public void doShowAlerts() { if (alertPanel == null) { alertPanel = new DefaultAlertPanel(); } if (!confirmLeave()) { return; } setBold(viewPane, 4); setPanelName("Alerts"); setCurrentContentPage(alertPanel); setFocus(alertTasks); setSaveEnabled(false); doRefreshAlerts(true); } public void doShowExtensions() { if (extensionsPanel == null) { extensionsPanel = new ExtensionManagerPanel(); } final String workingId = startWorking("Loading extensions..."); if (confirmLeave()) { setBold(viewPane, 6); setPanelName("Extensions"); setCurrentContentPage(extensionsPanel); setFocus(extensionsTasks); refreshExtensions(); stopWorking(workingId); } } public void doLogout() { logout(false); } public boolean logout(boolean quit) { if (!confirmLeave()) { return false; } // MIRTH-3074 Remove the keyEventDispatcher to prevent memory leak. KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventDispatcher(keyEventDispatcher); statusUpdaterExecutor.shutdownNow(); if (currentContentPage == messageBrowser) { mirthClient.getServerConnection().abort(messageBrowser.getAbortOperations()); } userPreferences = Preferences.userNodeForPackage(Mirth.class); userPreferences.putInt("maximizedState", getExtendedState()); userPreferences.putInt("width", getWidth()); userPreferences.putInt("height", getHeight()); LoadedExtensions.getInstance().stopPlugins(); try { mirthClient.logout(); mirthClient.close(); this.dispose(); if (!quit) { LoginPanel.getInstance().initialize(PlatformUI.SERVER_URL, PlatformUI.CLIENT_VERSION, "", ""); } } catch (ClientException e) { alertThrowable(this, e); } return true; } public void doMoveDestinationDown() { channelEditPanel.moveDestinationDown(); } public void doMoveDestinationUp() { channelEditPanel.moveDestinationUp(); } public void doEditGlobalScripts() { if (globalScriptsPanel == null) { globalScriptsPanel = new GlobalScriptsPanel(); } final String workingId = startWorking("Loading global scripts..."); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { public Void doInBackground() { globalScriptsPanel.edit(); return null; } public void done() { editGlobalScripts(); stopWorking(workingId); } }; worker.execute(); } public void doEditCodeTemplates() { codeTemplatePanel.switchPanel(); } public void doValidateCurrentGlobalScript() { globalScriptsPanel.validateCurrentScript(); } public void doImportGlobalScripts() { String content = browseForFileString("XML"); if (content != null) { try { ObjectXMLSerializer serializer = ObjectXMLSerializer.getInstance(); @SuppressWarnings("unchecked") Map<String, String> importScripts = serializer.deserialize(content, Map.class); for (Entry<String, String> globalScriptEntry : importScripts.entrySet()) { importScripts.put(globalScriptEntry.getKey(), globalScriptEntry.getValue().replaceAll("com.webreach.mirth", "com.mirth.connect")); } if (importScripts.containsKey("Shutdown") && !importScripts.containsKey("Undeploy")) { importScripts.put("Undeploy", importScripts.get("Shutdown")); importScripts.remove("Shutdown"); } globalScriptsPanel.importAllScripts(importScripts); } catch (Exception e) { alertThrowable(this, e, "Invalid scripts file. " + e.getMessage()); } } } public void doExportGlobalScripts() { if (changesHaveBeenMade()) { if (alertOption(this, "You must save your global scripts before exporting. Would you like to save them now?")) { String validationMessage = globalScriptsPanel.validateAllScripts(); if (validationMessage != null) { alertCustomError(this, validationMessage, CustomErrorDialog.ERROR_VALIDATING_GLOBAL_SCRIPTS); return; } globalScriptsPanel.save(); setSaveEnabled(false); } else { return; } } ObjectXMLSerializer serializer = ObjectXMLSerializer.getInstance(); String globalScriptsXML = serializer.serialize(globalScriptsPanel.exportAllScripts()); exportFile(globalScriptsXML, null, "XML", "Global Scripts export"); } public void doValidateChannelScripts() { channelEditPanel.validateScripts(); } public boolean doSaveGlobalScripts() { String validationMessage = globalScriptsPanel.validateAllScripts(); if (validationMessage != null) { alertCustomError(this, validationMessage, CustomErrorDialog.ERROR_VALIDATING_GLOBAL_SCRIPTS); return false; } final String workingId = startWorking("Saving global scripts..."); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { public Void doInBackground() { globalScriptsPanel.save(); return null; } public void done() { setSaveEnabled(false); stopWorking(workingId); } }; worker.execute(); return true; } public synchronized void increaseSafeErrorFailCount(String safeErrorKey) { int safeErrorFailCount = getSafeErrorFailCount(safeErrorKey) + 1; this.safeErrorFailCountMap.put(safeErrorKey, safeErrorFailCount); } public synchronized void resetSafeErrorFailCount(String safeErrorKey) { this.safeErrorFailCountMap.put(safeErrorKey, 0); } public synchronized int getSafeErrorFailCount(String safeErrorKey) { if (safeErrorFailCountMap.containsKey(safeErrorKey)) { return safeErrorFailCountMap.get(safeErrorKey); } else { return 0; } } public void doRefreshStatuses() { doRefreshStatuses(true); } public void doRefreshStatuses(boolean queue) { QueuingSwingWorkerTask<Void, DashboardStatus> task = new QueuingSwingWorkerTask<Void, DashboardStatus>( "doRefreshStatuses", "Loading statistics...") { @Override public Void doInBackground() { try { channelPanel.retrieveGroups(); channelPanel.retrieveDependencies(); for (DashboardColumnPlugin plugin : LoadedExtensions.getInstance().getDashboardColumnPlugins() .values()) { plugin.tableUpdate(status); } DashboardChannelInfo dashboardStatusList = mirthClient .getDashboardChannelInfo(REFRESH_BLOCK_SIZE); status = dashboardStatusList.getDashboardStatuses(); Set<String> remainingIds = dashboardStatusList.getRemainingChannelIds(); if (status != null) { publish(status.toArray(new DashboardStatus[status.size()])); if (CollectionUtils.isNotEmpty(remainingIds)) { Set<String> statusChannelIds = new HashSet<String>( Math.min(remainingIds.size(), REFRESH_BLOCK_SIZE)); for (Iterator<String> it = remainingIds.iterator(); it.hasNext();) { statusChannelIds.add(it.next()); if (!it.hasNext() || statusChannelIds.size() == REFRESH_BLOCK_SIZE) { // Processing a new block, retrieve dashboard statuses from server List<DashboardStatus> intermediateStatusList = mirthClient .getChannelStatusList(statusChannelIds); // Publish the intermediate statuses publish(intermediateStatusList .toArray(new DashboardStatus[intermediateStatusList.size()])); // Add the statuses to the master list status.addAll(intermediateStatusList); // Clear the set of channel IDs statusChannelIds.clear(); } } } } } catch (ClientException e) { status = null; alertThrowable(PlatformUI.MIRTH_FRAME, e, e.getMessage(), false, TaskConstants.DASHBOARD_REFRESH); } return null; } @Override public void process(List<DashboardStatus> chunks) { logger.debug("Processing chunk: " + (chunks != null ? chunks.size() : "null")); if (chunks != null) { TableState tableState = dashboardPanel.getCurrentTableState(); dashboardPanel.updateTableChannelNodes(chunks); dashboardPanel.updateTableState(tableState); } } @Override public void done() { if (status != null) { TableState tableState = dashboardPanel.getCurrentTableState(); updateChannelTags(true); dashboardPanel.finishUpdatingTable(status, channelPanel.getCachedGroupStatuses().values()); dashboardPanel.updateTableState(tableState); } } }; new QueuingSwingWorker<Void, DashboardStatus>(task, queue).executeDelegate(); } public void doStart() { final Set<DashboardStatus> selectedStatuses = dashboardPanel.getSelectedChannelStatuses(); if (selectedStatuses.size() == 0) { return; } if (!getStatusesWithDependencies(selectedStatuses, ChannelTask.START_RESUME)) { return; } final String workingId = startWorking("Starting or resuming channels..."); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { public Void doInBackground() { Set<String> startChannelIds = new HashSet<String>(); Set<String> resumeChannelIds = new HashSet<String>(); for (DashboardStatus dashboardStatus : selectedStatuses) { if (dashboardStatus.getState() == DeployedState.PAUSED) { resumeChannelIds.add(dashboardStatus.getChannelId()); } else { startChannelIds.add(dashboardStatus.getChannelId()); } } try { if (!startChannelIds.isEmpty()) { mirthClient.startChannels(startChannelIds); } if (!resumeChannelIds.isEmpty()) { mirthClient.resumeChannels(resumeChannelIds); } } catch (ClientException e) { alertThrowable(PlatformUI.MIRTH_FRAME, e); } return null; } public void done() { doRefreshStatuses(true); stopWorking(workingId); } }; worker.execute(); } public void doStop() { final Set<DashboardStatus> selectedStatuses = dashboardPanel.getSelectedChannelStatuses(); if (selectedStatuses.size() == 0) { return; } if (!getStatusesWithDependencies(selectedStatuses, ChannelTask.STOP)) { return; } final String workingId = startWorking("Stopping channel..."); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { public Void doInBackground() { Set<String> channelIds = new HashSet<String>(); for (DashboardStatus dashboardStatus : selectedStatuses) { channelIds.add(dashboardStatus.getChannelId()); } try { if (!channelIds.isEmpty()) { mirthClient.stopChannels(channelIds); } } catch (ClientException e) { alertThrowable(PlatformUI.MIRTH_FRAME, e); } return null; } public void done() { doRefreshStatuses(true); stopWorking(workingId); } }; worker.execute(); } public void doHalt() { final Set<DashboardStatus> selectedStatuses = dashboardPanel.getSelectedChannelStatuses(); int size = selectedStatuses.size(); if (size == 0 || !alertOption(this, "Are you sure you want to halt " + (size == 1 ? "this channel" : "these channels") + "?")) { return; } final String workingId = startWorking("Halting channels..."); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { public Void doInBackground() { Set<String> channelIds = new HashSet<String>(); for (DashboardStatus dashboardStatus : selectedStatuses) { channelIds.add(dashboardStatus.getChannelId()); } try { if (!channelIds.isEmpty()) { mirthClient.haltChannels(channelIds); } } catch (ClientException e) { alertThrowable(PlatformUI.MIRTH_FRAME, e); } return null; } public void done() { doRefreshStatuses(true); stopWorking(workingId); } }; worker.execute(); } public void doPause() { final Set<DashboardStatus> selectedChannelStatuses = dashboardPanel.getSelectedChannelStatuses(); if (selectedChannelStatuses.size() == 0) { return; } if (!getStatusesWithDependencies(selectedChannelStatuses, ChannelTask.PAUSE)) { return; } final String workingId = startWorking("Pausing channels..."); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { public Void doInBackground() { Set<String> channelIds = new HashSet<String>(); for (DashboardStatus dashboardStatus : selectedChannelStatuses) { channelIds.add(dashboardStatus.getChannelId()); } try { if (!channelIds.isEmpty()) { mirthClient.pauseChannels(channelIds); } } catch (ClientException e) { alertThrowable(PlatformUI.MIRTH_FRAME, e); } return null; } public void done() { doRefreshStatuses(true); stopWorking(workingId); } }; worker.execute(); } public void doStartConnector() { final List<DashboardStatus> selectedStatuses = dashboardPanel.getSelectedStatuses(); if (selectedStatuses.size() == 0) { return; } final String workingId = startWorking("Starting connectors..."); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { public Void doInBackground() { Map<String, List<Integer>> connectorInfo = new HashMap<String, List<Integer>>(); for (DashboardStatus dashboardStatus : selectedStatuses) { String channelId = dashboardStatus.getChannelId(); Integer metaDataId = dashboardStatus.getMetaDataId(); if (metaDataId != null) { if (!connectorInfo.containsKey(channelId)) { connectorInfo.put(channelId, new ArrayList<Integer>()); } connectorInfo.get(channelId).add(metaDataId); } } try { if (!connectorInfo.isEmpty()) { mirthClient.startConnectors(connectorInfo); } } catch (ClientException e) { alertThrowable(PlatformUI.MIRTH_FRAME, e); } return null; } public void done() { doRefreshStatuses(true); stopWorking(workingId); } }; worker.execute(); } public void doStopConnector() { final List<DashboardStatus> selectedStatuses = dashboardPanel.getSelectedStatuses(); if (selectedStatuses.size() == 0) { return; } boolean warnQueueDisabled = false; for (Iterator<DashboardStatus> it = selectedStatuses.iterator(); it.hasNext();) { DashboardStatus dashboardStatus = it.next(); if (dashboardStatus.getMetaDataId() != 0 && !dashboardStatus.isQueueEnabled()) { warnQueueDisabled = true; it.remove(); } } final String workingId = startWorking("Stopping connectors..."); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { public Void doInBackground() { Map<String, List<Integer>> connectorInfo = new HashMap<String, List<Integer>>(); for (DashboardStatus dashboardStatus : selectedStatuses) { String channelId = dashboardStatus.getChannelId(); Integer metaDataId = dashboardStatus.getMetaDataId(); if (metaDataId != null) { if (!connectorInfo.containsKey(channelId)) { connectorInfo.put(channelId, new ArrayList<Integer>()); } connectorInfo.get(channelId).add(metaDataId); } } try { if (!connectorInfo.isEmpty()) { mirthClient.stopConnectors(connectorInfo); } } catch (ClientException e) { alertThrowable(PlatformUI.MIRTH_FRAME, e); } return null; } public void done() { doRefreshStatuses(true); stopWorking(workingId); } }; worker.execute(); if (warnQueueDisabled) { alertWarning(this, "<html>One or more destination connectors were not stopped because queueing was not enabled.<br>Queueing must be enabled for a destination connector to be stopped individually.</html>"); } } public void doNewDestination() { channelEditPanel.addNewDestination(); } public void doDeleteDestination() { if (!alertOption(this, "Are you sure you want to delete this destination?")) { return; } channelEditPanel.deleteDestination(); } public void doCloneDestination() { channelEditPanel.cloneDestination(); } public void doEnableDestination() { channelEditPanel.enableDestination(); } public void doDisableDestination() { channelEditPanel.disableDestination(); } public void doNewUser() { new UserDialog(null); } public void doEditUser() { int index = userPanel.getUserIndex(); if (index == UIConstants.ERROR_CONSTANT) { alertWarning(this, "User no longer exists."); } else { new UserDialog(users.get(index)); } } public void doDeleteUser() { if (!alertOption(this, "Are you sure you want to delete this user?")) { return; } final String workingId = startWorking("Deleting user..."); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { public Void doInBackground() { if (users.size() == 1) { alertWarning(PlatformUI.MIRTH_FRAME, "You must have at least one user account."); return null; } int userToDelete = userPanel.getUserIndex(); try { if (userToDelete != UIConstants.ERROR_CONSTANT) { mirthClient.removeUser(users.get(userToDelete).getId()); retrieveUsers(); } } catch (ClientException e) { alertThrowable(PlatformUI.MIRTH_FRAME, e); } return null; } public void done() { userPanel.updateUserTable(); userPanel.deselectRows(); stopWorking(workingId); } }; worker.execute(); } public void doRefreshUser() { final String workingId = startWorking("Loading users..."); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { public Void doInBackground() { refreshUser(); return null; } public void done() { stopWorking(workingId); } }; worker.execute(); } public void refreshUser() { User user = null; String userName = null; int index = userPanel.getUserIndex(); if (index != UIConstants.ERROR_CONSTANT) { user = users.get(index); } try { retrieveUsers(); userPanel.updateUserTable(); if (user != null) { for (int i = 0; i < users.size(); i++) { if (user.equals(users.get(i))) { userName = users.get(i).getUsername(); } } } } catch (ClientException e) { alertThrowable(this, e); } // as long as the channel was not deleted if (userName != null) { userPanel.setSelectedUser(userName); } } public void doDeployFromChannelView() { String channelId = channelEditPanel.currentChannel.getId(); if (isSaveEnabled()) { if (alertOption(PlatformUI.MIRTH_FRAME, "<html>This channel will be saved before it is deployed.<br/>Are you sure you want to save and deploy this channel?</html>")) { if (channelEditPanel.saveChanges()) { setSaveEnabled(false); } else { return; } } else { return; } } else { if (!alertOption(PlatformUI.MIRTH_FRAME, "Are you sure you want to deploy this channel?")) { return; } } ChannelStatus channelStatus = channelPanel.getCachedChannelStatuses().get(channelId); if (channelStatus == null) { alertWarning(this, "The channel cannot be found and will not be deployed."); return; } if (!channelStatus.getChannel().getExportData().getMetadata().isEnabled()) { alertWarning(this, "The channel is disabled and will not be deployed."); return; } deployChannel(Collections.singleton(channelId)); } public void deployChannel(final Set<String> selectedChannelIds) { if (CollectionUtils.isNotEmpty(selectedChannelIds)) { String plural = (selectedChannelIds.size() > 1) ? "s" : ""; final String workingId = startWorking("Deploying channel" + plural + "..."); dashboardPanel.deselectRows(false); doShowDashboard(); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { public Void doInBackground() { try { mirthClient.deployChannels(selectedChannelIds); } catch (ClientException e) { alertThrowable(PlatformUI.MIRTH_FRAME, e); } return null; } public void done() { stopWorking(workingId); doRefreshStatuses(true); } }; worker.execute(); } } public enum ChannelTask { DEPLOY("deploy", "(re)deployed", true), UNDEPLOY("undeploy", "undeployed", false), START_RESUME( "start/resume", "started or resumed", true), STOP("stop", "stopped", false), PAUSE("pause", "paused", false); private String value; private String futurePassive; private boolean forwardOrder; private ChannelTask(String value, String futurePassive, boolean forwardOrder) { this.value = value; this.futurePassive = futurePassive; this.forwardOrder = forwardOrder; } public String getFuturePassive() { return futurePassive; } public boolean isForwardOrder() { return forwardOrder; } @Override public String toString() { return value; } } /** * Adds dependent/dependency dashboard statuses to the given set, based on the type of task * being performed. */ private boolean getStatusesWithDependencies(Set<DashboardStatus> selectedDashboardStatuses, ChannelTask task) { try { ChannelDependencyGraph channelDependencyGraph = new ChannelDependencyGraph( channelPanel.getCachedChannelDependencies()); Set<String> selectedChannelIds = new HashSet<String>(); Set<String> channelIdsToHandle = new HashSet<String>(); Map<String, DashboardStatus> statusMap = new HashMap<String, DashboardStatus>(); for (DashboardStatus dashboardStatus : status) { statusMap.put(dashboardStatus.getChannelId(), dashboardStatus); } // For each selected channel, add any dependent/dependency channels as necessary for (DashboardStatus dashboardStatus : selectedDashboardStatuses) { selectedChannelIds.add(dashboardStatus.getChannelId()); addChannelToTaskSet(dashboardStatus.getChannelId(), channelDependencyGraph, statusMap, channelIdsToHandle, task); } // If additional channels were added to the set, we need to prompt the user if (!CollectionUtils.subtract(channelIdsToHandle, selectedChannelIds).isEmpty()) { ChannelDependenciesWarningDialog dialog = new ChannelDependenciesWarningDialog(task, channelPanel.getCachedChannelDependencies(), selectedChannelIds, channelIdsToHandle); if (dialog.getResult() == JOptionPane.OK_OPTION) { if (dialog.isIncludeOtherChannels()) { for (String channelId : channelIdsToHandle) { selectedDashboardStatuses.add(statusMap.get(channelId)); } } } else { return false; } } } catch (ChannelDependencyException e) { // Should never happen e.printStackTrace(); } return true; } private void addChannelToTaskSet(String channelId, ChannelDependencyGraph channelDependencyGraph, Map<String, DashboardStatus> statusMap, Set<String> channelIdsToHandle, ChannelTask task) { if (!channelIdsToHandle.add(channelId)) { return; } DirectedAcyclicGraphNode<String> node = channelDependencyGraph.getNode(channelId); if (node != null) { if (task.isForwardOrder()) { // Add dependency channels for the start/resume task. for (String dependencyChannelId : node.getDirectDependencyElements()) { // Only add the dependency channel if it's currently deployed and not already started. if (statusMap.containsKey(dependencyChannelId)) { DashboardStatus dashboardStatus = statusMap.get(dependencyChannelId); if (dashboardStatus.getState() != DeployedState.STARTED) { addChannelToTaskSet(dependencyChannelId, channelDependencyGraph, statusMap, channelIdsToHandle, task); } } } } else { // Add dependent channels for the undeploy/stop/pause tasks. for (String dependentChannelId : node.getDirectDependentElements()) { /* * Only add the dependent channel if it's currently deployed, and it's not * already stopped/paused (depending on the task being performed). */ if (statusMap.containsKey(dependentChannelId)) { DashboardStatus dashboardStatus = statusMap.get(dependentChannelId); if (task == ChannelTask.UNDEPLOY || task == ChannelTask.STOP && dashboardStatus.getState() != DeployedState.STOPPED || task == ChannelTask.PAUSE && dashboardStatus.getState() != DeployedState.PAUSED && dashboardStatus.getState() != DeployedState.STOPPED) { addChannelToTaskSet(dependentChannelId, channelDependencyGraph, statusMap, channelIdsToHandle, task); } } } } } } public void doUndeployChannel() { final Set<DashboardStatus> selectedChannelStatuses = dashboardPanel.getSelectedChannelStatuses(); if (selectedChannelStatuses.size() == 0) { return; } if (!getStatusesWithDependencies(selectedChannelStatuses, ChannelTask.UNDEPLOY)) { return; } dashboardPanel.deselectRows(false); String plural = (selectedChannelStatuses.size() > 1) ? "s" : ""; final String workingId = startWorking("Undeploying channel" + plural + "..."); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { public Void doInBackground() { try { Set<String> channelIds = new LinkedHashSet<String>(); for (DashboardStatus channelStatus : selectedChannelStatuses) { channelIds.add(channelStatus.getChannelId()); } mirthClient.undeployChannels(channelIds); } catch (ClientException e) { alertThrowable(PlatformUI.MIRTH_FRAME, e); } return null; } public void done() { stopWorking(workingId); doRefreshStatuses(true); } }; worker.execute(); } public void doSaveChannel() { final String workingId = startWorking("Saving channel..."); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { public Void doInBackground() { if (changesHaveBeenMade() || currentContentPage == channelEditPanel.transformerPane || currentContentPage == channelEditPanel.filterPane) { if (channelEditPanel.saveChanges()) { setSaveEnabled(false); } return null; } else { return null; } } public void done() { stopWorking(workingId); } }; worker.execute(); } public boolean changesHaveBeenMade() { if (currentContentPage == channelPanel) { return channelPanel.changesHaveBeenMade(); } else if (channelEditPanel != null && currentContentPage == channelEditPanel) { return channelEditTasks.getContentPane().getComponent(0).isVisible(); } else if (channelEditPanel != null && currentContentPage == channelEditPanel.transformerPane) { return channelEditPanel.transformerPane.modified; } else if (channelEditPanel != null && currentContentPage == channelEditPanel.filterPane) { return channelEditPanel.filterPane.modified; } else if (settingsPane != null && currentContentPage == settingsPane) { return settingsPane.getCurrentSettingsPanel().isSaveEnabled(); } else if (alertEditPanel != null && currentContentPage == alertEditPanel) { return alertEditTasks.getContentPane().getComponent(0).isVisible(); } else if (globalScriptsPanel != null && currentContentPage == globalScriptsPanel) { return globalScriptsTasks.getContentPane().getComponent(0).isVisible(); } else if (currentContentPage == codeTemplatePanel) { return codeTemplatePanel.changesHaveBeenMade(); } else { return false; } } public void doShowMessages() { if (messageBrowser == null) { messageBrowser = new MessageBrowser(); } String id = ""; String channelName = ""; boolean channelDeployed = true; Integer channelRevision = null; final List<Integer> metaDataIds = new ArrayList<Integer>(); if (currentContentPage == dashboardPanel) { List<DashboardStatus> selectedStatuses = dashboardPanel.getSelectedStatuses(); Set<DashboardStatus> selectedChannelStatuses = dashboardPanel.getSelectedChannelStatuses(); if (selectedStatuses.size() == 0) { return; } if (selectedChannelStatuses.size() > 1) { JOptionPane.showMessageDialog(Frame.this, "This operation can only be performed on a single channel."); return; } for (DashboardStatus status : selectedStatuses) { metaDataIds.add(status.getMetaDataId()); } id = selectedStatuses.get(0).getChannelId(); channelName = selectedChannelStatuses.iterator().next().getName(); channelRevision = 0; } else if (currentContentPage == channelPanel) { Channel selectedChannel = channelPanel.getSelectedChannels().get(0); metaDataIds.add(null); id = selectedChannel.getId(); channelName = selectedChannel.getName(); channelRevision = selectedChannel.getRevision(); channelDeployed = false; for (DashboardStatus dashStatus : status) { if (dashStatus.getChannelId().equals(id)) { channelDeployed = true; } } } setBold(viewPane, -1); setPanelName("Channel Messages - " + channelName); setCurrentContentPage(messageBrowser); setFocus(messageTasks); final String channelId = id; final boolean isChannelDeployed = channelDeployed; final String workingId = startWorking("Retrieving channel metadata..."); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { Map<Integer, String> connectors; List<MetaDataColumn> metaDataColumns; public Void doInBackground() { try { connectors = mirthClient.getConnectorNames(channelId); metaDataColumns = mirthClient.getMetaDataColumns(channelId); } catch (ClientException e) { alertThrowable(PlatformUI.MIRTH_FRAME, e); } return null; } public void done() { stopWorking(workingId); if (connectors == null || metaDataColumns == null) { alertError(PlatformUI.MIRTH_FRAME, "Could not retrieve metadata for channel."); } else { messageBrowser.loadChannel(channelId, connectors, metaDataColumns, metaDataIds, isChannelDeployed); } } }; worker.execute(); } public void doShowEvents() { doShowEvents(null); } public void doShowEvents(String eventNameFilter) { if (!confirmLeave()) { return; } if (eventBrowser == null) { eventBrowser = new EventBrowser(); } setBold(viewPane, 5); setPanelName("Events"); setCurrentContentPage(eventBrowser); setFocus(eventTasks); eventBrowser.loadNew(eventNameFilter); } public void doEditTransformer() { channelEditPanel.transformerPane.resizePanes(); String name = channelEditPanel.editTransformer(); setPanelName("Edit Channel - " + channelEditPanel.currentChannel.getName() + " - " + name + " Transformer"); } public void doEditResponseTransformer() { channelEditPanel.transformerPane.resizePanes(); String name = channelEditPanel.editResponseTransformer(); setPanelName("Edit Channel - " + channelEditPanel.currentChannel.getName() + " - " + name + " Response Transformer"); } public void doEditFilter() { channelEditPanel.filterPane.resizePanes(); String name = channelEditPanel.editFilter(); setPanelName("Edit Channel - " + channelEditPanel.currentChannel.getName() + " - " + name + " Filter"); } public void updateFilterTaskName(int rules) { updateFilterOrTransformerTaskName(UIConstants.EDIT_FILTER, UIConstants.EDIT_FILTER_TASK_NUMBER, rules, false); } public void updateTransformerTaskName(int steps, boolean outboundTemplate) { updateFilterOrTransformerTaskName(UIConstants.EDIT_TRANSFORMER, UIConstants.EDIT_TRANSFORMER_TASK_NUMBER, steps, outboundTemplate); } public void updateResponseTransformerTaskName(int steps, boolean outboundTemplate) { updateFilterOrTransformerTaskName(UIConstants.EDIT_RESPONSE_TRANSFORMER, UIConstants.EDIT_RESPONSE_TRANSFORMER_TASK_NUMBER, steps, outboundTemplate); } private void updateFilterOrTransformerTaskName(String taskName, int componentIndex, int rulesOrSteps, boolean outboundTemplate) { if (rulesOrSteps > 0) { taskName += " (" + rulesOrSteps + ")"; } else if (outboundTemplate) { taskName += " (0)"; } ((JXHyperlink) channelEditTasks.getContentPane().getComponent(componentIndex)).setText(taskName); ((JMenuItem) channelEditPopupMenu.getComponent(componentIndex)).setText(taskName); } public void doValidate() { channelEditPanel.doValidate(); } public boolean doExportChannel() { return channelPanel.doExportChannel(); } /** * Import a file with the default defined file filter type. * * @return */ public String browseForFileString(String fileExtension) { File file = browseForFile(fileExtension); if (file != null) { return readFileToString(file); } return null; } /** * Read the bytes from a file with the default defined file filter type. * * @return */ public byte[] browseForFileBytes(String fileExtension) { File file = browseForFile(fileExtension); if (file != null) { try { return FileUtils.readFileToByteArray(file); } catch (IOException e) { alertError(this, "Unable to read file."); } } return null; } public String readFileToString(File file) { try { String content = FileUtils.readFileToString(file, UIConstants.CHARSET); if (StringUtils.startsWith(content, EncryptionSettings.ENCRYPTION_PREFIX)) { return mirthClient.getEncryptor() .decrypt(StringUtils.removeStart(content, EncryptionSettings.ENCRYPTION_PREFIX)); } else { return content; } } catch (IOException e) { alertError(this, "Unable to read file."); } return null; } public File browseForFile(String fileExtension) { JFileChooser importFileChooser = new JFileChooser(); if (fileExtension != null) { importFileChooser.setFileFilter(new MirthFileFilter(fileExtension)); } File currentDir = new File(userPreferences.get("currentDirectory", "")); if (currentDir.exists()) { importFileChooser.setCurrentDirectory(currentDir); } if (importFileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { userPreferences.put("currentDirectory", importFileChooser.getCurrentDirectory().getPath()); return importFileChooser.getSelectedFile(); } return null; } /** * Creates a File with the default defined file filter type, but does not yet write to it. * * @param defaultFileName * @param fileExtension * @return */ public File createFileForExport(String defaultFileName, String fileExtension) { JFileChooser exportFileChooser = new JFileChooser(); if (defaultFileName != null) { exportFileChooser.setSelectedFile(new File(defaultFileName)); } if (fileExtension != null) { exportFileChooser.setFileFilter(new MirthFileFilter(fileExtension)); } File currentDir = new File(userPreferences.get("currentDirectory", "")); if (currentDir.exists()) { exportFileChooser.setCurrentDirectory(currentDir); } if (exportFileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) { userPreferences.put("currentDirectory", exportFileChooser.getCurrentDirectory().getPath()); File exportFile = exportFileChooser.getSelectedFile(); if ((exportFile.getName().length() < 4) || !FilenameUtils.getExtension(exportFile.getName()).equalsIgnoreCase(fileExtension)) { exportFile = new File(exportFile.getAbsolutePath() + "." + fileExtension.toLowerCase()); } if (exportFile.exists()) { if (!alertOption(this, "This file already exists. Would you like to overwrite it?")) { return null; } } return exportFile; } else { return null; } } /** * Export a file with the default defined file filter type. * * @param fileContents * @param fileName * @return */ public boolean exportFile(String fileContents, String defaultFileName, String fileExtension, String name) { return exportFile(fileContents, createFileForExport(defaultFileName, fileExtension), name); } public boolean exportFile(String fileContents, File exportFile, String name) { if (exportFile != null) { try { String contentToWrite = null; if (mirthClient.isEncryptExport()) { contentToWrite = EncryptionSettings.ENCRYPTION_PREFIX + mirthClient.getEncryptor().encrypt(fileContents); } else { contentToWrite = fileContents; } FileUtils.writeStringToFile(exportFile, contentToWrite, UIConstants.CHARSET); alertInformation(this, name + " was written to " + exportFile.getPath() + "."); } catch (IOException ex) { alertError(this, "File could not be written."); return false; } return true; } else { return false; } } public void doImportConnector() { String content = browseForFileString("XML"); if (content != null) { try { channelEditPanel .importConnector(ObjectXMLSerializer.getInstance().deserialize(content, Connector.class)); } catch (Exception e) { alertThrowable(this, e); } } } public void doExportConnector() { if (changesHaveBeenMade()) { if (alertOption(this, "This channel has been modified. You must save the channel changes before you can export. Would you like to save them now?")) { if (!channelEditPanel.saveChanges()) { return; } } else { return; } setSaveEnabled(false); } Connector connector = channelEditPanel.exportSelectedConnector(); // Update resource names updateResourceNames(connector); ObjectXMLSerializer serializer = ObjectXMLSerializer.getInstance(); String connectorXML = serializer.serialize(connector); String fileName = channelEditPanel.currentChannel.getName(); if (connector.getMode().equals(Mode.SOURCE)) { fileName += " Source"; } else { fileName += " " + connector.getName(); } exportFile(connectorXML, fileName, "XML", "Connector"); } public void doRefreshMessages() { messageBrowser.refresh(null, true); } public void doSendMessage() { String channelId = null; List<Integer> selectedMetaDataIds = null; if (currentContentPage == dashboardPanel) { List<DashboardStatus> selectedStatuses = dashboardPanel.getSelectedStatuses(); channelId = selectedStatuses.get(0).getChannelId(); selectedMetaDataIds = new ArrayList<Integer>(); for (DashboardStatus status : selectedStatuses) { if (status.getChannelId() != channelId) { JOptionPane.showMessageDialog(Frame.this, "This operation can only be performed on a single channel."); return; } if (status.getStatusType() == StatusType.CHANNEL) { selectedMetaDataIds = null; } else if (selectedMetaDataIds != null) { Integer metaDataId = status.getMetaDataId(); if (metaDataId != null) { selectedMetaDataIds.add(metaDataId); } } } } else if (currentContentPage == messageBrowser) { channelId = messageBrowser.getChannelId(); } /* * If the user has not yet navigated to channels at this point, the cache (channelStatuses * object) will return null, and the resulting block will pull down the channelStatus for * the given id. */ ChannelStatus channelStatus = channelPanel.getCachedChannelStatuses().get(channelId); if (channelStatus == null) { try { Map<String, ChannelHeader> channelHeaders = new HashMap<String, ChannelHeader>(); channelHeaders.put(channelId, new ChannelHeader(0, null, true)); channelPanel.updateChannelStatuses(mirthClient.getChannelSummary(channelHeaders, true)); channelStatus = channelPanel.getCachedChannelStatuses().get(channelId); } catch (ClientException e) { alertThrowable(PlatformUI.MIRTH_FRAME, e); } } if (channelId == null || channelStatus == null) { alertError(this, "Channel no longer exists!"); return; } editMessageDialog.setPropertiesAndShow("", channelStatus.getChannel().getSourceConnector().getTransformer().getInboundDataType(), channelStatus.getChannel().getId(), dashboardPanel.getDestinationConnectorNames(channelId), selectedMetaDataIds, new HashMap<String, Object>()); } public void doExportMessages() { if (messageExportDialog == null) { messageExportDialog = new MessageExportDialog(); } messageExportDialog.setEncryptor(mirthClient.getEncryptor()); messageExportDialog.setMessageFilter(messageBrowser.getMessageFilter()); messageExportDialog.setPageSize(messageBrowser.getPageSize()); messageExportDialog.setChannelId(messageBrowser.getChannelId()); messageExportDialog.setLocationRelativeTo(this); messageExportDialog.setVisible(true); } public void doImportMessages() { if (messageImportDialog == null) { messageImportDialog = new MessageImportDialog(); } messageImportDialog.setChannelId(messageBrowser.getChannelId()); messageImportDialog.setMessageBrowser(messageBrowser); messageImportDialog.setLocationRelativeTo(this); messageImportDialog.setVisible(true); } public void doRemoveAllMessages() { if (removeMessagesDialog == null) { removeMessagesDialog = new RemoveMessagesDialog(this, true); } Set<String> channelIds = new HashSet<String>(); boolean restartCheckboxEnabled = false; if (currentContentPage instanceof MessageBrowser) { String channelId = ((MessageBrowser) currentContentPage).getChannelId(); channelIds.add(channelId); for (DashboardStatus channelStatus : status) { if (channelStatus.getChannelId().equals(channelId)) { if (!channelStatus.getState().equals(DeployedState.STOPPED) && !restartCheckboxEnabled) { restartCheckboxEnabled = true; } } } } else { for (DashboardStatus channelStatus : dashboardPanel.getSelectedChannelStatuses()) { channelIds.add(channelStatus.getChannelId()); if (!channelStatus.getState().equals(DeployedState.STOPPED) && !restartCheckboxEnabled) { restartCheckboxEnabled = true; } } } removeMessagesDialog.init(channelIds, restartCheckboxEnabled); removeMessagesDialog.setLocationRelativeTo(this); removeMessagesDialog.setVisible(true); } public void doClearStats() { List<DashboardStatus> channelStatuses = dashboardPanel.getSelectedStatusesRecursive(); if (channelStatuses.size() != 0) { new DeleteStatisticsDialog(channelStatuses); } else { dashboardPanel.deselectRows(false); } } public void clearStats(List<DashboardStatus> statusesToClear, final boolean deleteReceived, final boolean deleteFiltered, final boolean deleteSent, final boolean deleteErrored) { final String workingId = startWorking("Clearing statistics..."); Map<String, List<Integer>> channelConnectorMap = new HashMap<String, List<Integer>>(); for (DashboardStatus status : statusesToClear) { String channelId = status.getChannelId(); Integer metaDataId = status.getMetaDataId(); List<Integer> metaDataIds = channelConnectorMap.get(channelId); if (metaDataIds == null) { metaDataIds = new ArrayList<Integer>(); channelConnectorMap.put(channelId, metaDataIds); } metaDataIds.add(metaDataId); } final Map<String, List<Integer>> channelConnectorMapFinal = channelConnectorMap; SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { public Void doInBackground() { try { mirthClient.clearStatistics(channelConnectorMapFinal, deleteReceived, deleteFiltered, deleteSent, deleteErrored); } catch (ClientException e) { alertThrowable(PlatformUI.MIRTH_FRAME, e); } return null; } public void done() { doRefreshStatuses(true); stopWorking(workingId); } }; worker.execute(); } public void doRemoveFilteredMessages() { if (alertOption(this, "<html>Are you sure you would like to remove all currently filtered messages (including QUEUED) in this channel?<br>Channel must be stopped for unfinished messages to be removed.<br><font size='1'><br></font>WARNING: Removing a Source message will remove all of its destinations.</html>")) { final String workingId = startWorking("Removing messages..."); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { public Void doInBackground() { try { mirthClient.removeMessages(messageBrowser.getChannelId(), messageBrowser.getMessageFilter()); } catch (ClientException e) { if (e instanceof RequestAbortedException) { // The client is no longer waiting for the delete request } else { alertThrowable(PlatformUI.MIRTH_FRAME, e); } } return null; } public void done() { if (currentContentPage == dashboardPanel) { doRefreshStatuses(true); } else if (currentContentPage == messageBrowser) { messageBrowser.refresh(1, true); } stopWorking(workingId); } }; worker.execute(); } } public void doRemoveMessage() { final Integer metaDataId = messageBrowser.getSelectedMetaDataId(); final Long messageId = messageBrowser.getSelectedMessageId(); final String channelId = messageBrowser.getChannelId(); if (alertOption(this, "<html>Are you sure you would like to remove the selected message?<br>Channel must be stopped for an unfinished message to be removed.<br><font size='1'><br></font>WARNING: Removing a Source message will remove all of its destinations.</html>")) { final String workingId = startWorking("Removing message..."); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { public Void doInBackground() { try { MessageFilter filter = new MessageFilter(); filter.setMinMessageId(messageId); filter.setMaxMessageId(messageId); List<Integer> metaDataIds = new ArrayList<Integer>(); metaDataIds.add(metaDataId); filter.setIncludedMetaDataIds(metaDataIds); mirthClient.removeMessages(channelId, filter); } catch (ClientException e) { alertThrowable(PlatformUI.MIRTH_FRAME, e); } return null; } public void done() { if (currentContentPage == dashboardPanel) { doRefreshStatuses(true); } else if (currentContentPage == messageBrowser) { messageBrowser.refresh(null, false); } stopWorking(workingId); } }; worker.execute(); } } public void doReprocessFilteredMessages() { doReprocess(messageBrowser.getMessageFilter(), null, true); } public void doReprocessMessage() { Long messageId = messageBrowser.getSelectedMessageId(); if (messageBrowser.canReprocessMessage(messageId)) { MessageFilter filter = new MessageFilter(); filter.setMinMessageId(messageId); filter.setMaxMessageId(messageId); doReprocess(filter, messageBrowser.getSelectedMetaDataId(), false); } else { alertError(this, "Message " + messageId + " cannot be reprocessed because no source raw content was found."); } } private void doReprocess(final MessageFilter filter, final Integer selectedMetaDataId, final boolean showWarning) { final String workingId = startWorking("Retrieving Channels..."); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { public Void doInBackground() { if (channelPanel.getCachedChannelStatuses() == null || channelPanel.getCachedChannelStatuses().values().size() == 0) { channelPanel.retrieveChannels(); } return null; } public void done() { stopWorking(workingId); Map<Integer, String> destinationConnectors = new LinkedHashMap<Integer, String>(); destinationConnectors .putAll(dashboardPanel.getDestinationConnectorNames(messageBrowser.getChannelId())); new ReprocessMessagesDialog(messageBrowser.getChannelId(), filter, destinationConnectors, selectedMetaDataId, showWarning); } }; worker.execute(); } public void reprocessMessage(final String channelId, final MessageFilter filter, final boolean replace, final Collection<Integer> reprocessMetaDataIds) { final String workingId = startWorking("Reprocessing messages..."); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { public Void doInBackground() { try { mirthClient.reprocessMessages(channelId, filter, replace, reprocessMetaDataIds); } catch (ClientException e) { alertThrowable(PlatformUI.MIRTH_FRAME, e); } return null; } public void done() { messageBrowser.updateFilterButtonFont(Font.BOLD); stopWorking(workingId); } }; worker.execute(); } public void viewImage() { final String workingId = startWorking("Opening attachment..."); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { public Void doInBackground() { messageBrowser.viewAttachment(); stopWorking(workingId); return null; } public void done() { stopWorking(workingId); } }; worker.execute(); } public void doExportAttachment() { if (attachmentExportDialog == null) { attachmentExportDialog = new AttachmentExportDialog(); } attachmentExportDialog.setLocationRelativeTo(this); attachmentExportDialog.setVisible(true); } public void processMessage(final String channelId, final RawMessage rawMessage) { final String workingId = startWorking("Processing message..."); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { public Void doInBackground() { try { mirthClient.processMessage(channelId, rawMessage); } catch (ClientException e) { alertThrowable(PlatformUI.MIRTH_FRAME, e); } return null; } public void done() { if (currentContentPage == messageBrowser) { messageBrowser.updateFilterButtonFont(Font.BOLD); } stopWorking(workingId); } }; worker.execute(); } public void doRefreshEvents() { eventBrowser.refresh(null); } public void doRemoveAllEvents() { int option = JOptionPane.showConfirmDialog(this, "All events will be removed. Would you also like them to be\n" + "exported to a file on the server?"); if (option == JOptionPane.CANCEL_OPTION || option == JOptionPane.CLOSED_OPTION) { return; } final boolean export = (option == JOptionPane.YES_OPTION); final String workingId = startWorking("Clearing events..."); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { private String exportPath = null; public Void doInBackground() { try { if (export) { exportPath = mirthClient.exportAndRemoveAllEvents(); } else { mirthClient.removeAllEvents(); } } catch (ClientException e) { alertThrowable(PlatformUI.MIRTH_FRAME, e); } return null; } public void done() { eventBrowser.runSearch(); if (exportPath != null) { alertInformation(PlatformUI.MIRTH_FRAME, "Events have been exported to the following server path:\n" + exportPath); } stopWorking(workingId); } }; worker.execute(); } public void doExportAllEvents() { if (alertOption(this, "Are you sure you would like to export all events? An export\n" + "file will be placed in the exports directory on the server.")) { final String workingId = startWorking("Exporting events..."); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { private String exportPath = null; public Void doInBackground() { try { exportPath = mirthClient.exportAllEvents(); } catch (ClientException e) { alertThrowable(PlatformUI.MIRTH_FRAME, e); } return null; } public void done() { if (exportPath != null) { alertInformation(PlatformUI.MIRTH_FRAME, "Events have been exported to the following server path:\n" + exportPath); } stopWorking(workingId); } }; worker.execute(); } } public void doRefreshAlerts() { doRefreshAlerts(true); } public void doRefreshAlerts(boolean queue) { final List<String> selectedAlertIds = alertPanel.getSelectedAlertIds(); QueuingSwingWorkerTask<Void, Void> task = new QueuingSwingWorkerTask<Void, Void>("doRefreshAlerts", "Loading alerts...") { private List<AlertStatus> alertStatusList; public Void doInBackground() { try { alertStatusList = mirthClient.getAlertStatusList(); } catch (ClientException e) { alertThrowable(PlatformUI.MIRTH_FRAME, e); } return null; } public void done() { alertPanel.updateAlertTable(alertStatusList); alertPanel.setSelectedAlertIds(selectedAlertIds); } }; new QueuingSwingWorker<Void, Void>(task, queue).executeDelegate(); } public void doSaveAlerts() { if (changesHaveBeenMade()) { try { ServerSettings serverSettings = mirthClient.getServerSettings(); if (StringUtils.isBlank(serverSettings.getSmtpHost()) || StringUtils.isBlank(serverSettings.getSmtpPort())) { alertWarning(PlatformUI.MIRTH_FRAME, "The SMTP server on the settings page is not specified or is incomplete. An SMTP server is required to send email alerts."); } } catch (ClientException e) { alertThrowable(PlatformUI.MIRTH_FRAME, e, false); } final String workingId = startWorking("Saving alerts..."); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { public Void doInBackground() { if (alertEditPanel.saveAlert()) { setSaveEnabled(false); } return null; } public void done() { stopWorking(workingId); } }; worker.execute(); } } public void doDeleteAlert() { if (!alertOption(this, "Are you sure you want to delete the selected alert(s)?")) { return; } final String workingId = startWorking("Deleting alert..."); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { public Void doInBackground() { List<String> selectedAlertIds = alertPanel.getSelectedAlertIds(); for (String alertId : selectedAlertIds) { try { mirthClient.removeAlert(alertId); } catch (ClientException e) { alertThrowable(PlatformUI.MIRTH_FRAME, e); return null; } } alertPanel.updateAlertDetails(new HashSet<String>(selectedAlertIds)); return null; } public void done() { doRefreshAlerts(true); stopWorking(workingId); } }; worker.execute(); } public void doNewAlert() throws ClientException { AlertInfo alertInfo = mirthClient.getAlertInfo(channelPanel.getChannelHeaders()); channelPanel.updateChannelStatuses(alertInfo.getChangedChannels()); setupAlert(alertInfo.getProtocolOptions()); } public void doEditAlert() { if (isEditingAlert) { return; } else { isEditingAlert = true; } List<String> selectedAlertIds = alertPanel.getSelectedAlertIds(); if (selectedAlertIds.size() > 1) { JOptionPane.showMessageDialog(Frame.this, "This operation can only be performed on a single alert."); } else if (selectedAlertIds.size() == 0) { JOptionPane.showMessageDialog(Frame.this, "Alert no longer exists."); } else { try { AlertInfo alertInfo = mirthClient.getAlertInfo(selectedAlertIds.get(0), channelPanel.getChannelHeaders()); if (alertInfo.getModel() == null) { JOptionPane.showMessageDialog(Frame.this, "Alert no longer exists."); doRefreshAlerts(true); } else { channelPanel.updateChannelStatuses(alertInfo.getChangedChannels()); editAlert(alertInfo.getModel(), alertInfo.getProtocolOptions()); } } catch (ClientException e) { alertThrowable(this, e); } } isEditingAlert = false; } public void doEnableAlert() { final String workingId = startWorking("Enabling alert..."); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { public Void doInBackground() { List<String> selectedAlertIds = alertPanel.getSelectedAlertIds(); for (String alertId : selectedAlertIds) { try { mirthClient.enableAlert(alertId); } catch (ClientException e) { alertThrowable(PlatformUI.MIRTH_FRAME, e); return null; } } return null; } public void done() { doRefreshAlerts(true); stopWorking(workingId); } }; worker.execute(); } public void doDisableAlert() { final String workingId = startWorking("Enabling alert..."); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { public Void doInBackground() { List<String> selectedAlertIds = alertPanel.getSelectedAlertIds(); for (String alertId : selectedAlertIds) { try { mirthClient.disableAlert(alertId); } catch (ClientException e) { alertThrowable(PlatformUI.MIRTH_FRAME, e); return null; } } return null; } public void done() { doRefreshAlerts(true); stopWorking(workingId); } }; worker.execute(); } public void doExportAlert() { if (changesHaveBeenMade()) { if (alertOption(this, "This alert has been modified. You must save the alert changes before you can export. Would you like to save them now?")) { if (!alertEditPanel.saveAlert()) { return; } } else { return; } setSaveEnabled(false); } List<String> selectedAlertIds; if (currentContentPage == alertEditPanel) { selectedAlertIds = new ArrayList<String>(); String alertId = alertEditPanel.getAlertId(); if (alertId != null) { selectedAlertIds.add(alertId); } } else { selectedAlertIds = alertPanel.getSelectedAlertIds(); } if (CollectionUtils.isEmpty(selectedAlertIds)) { return; } AlertModel alert; try { alert = mirthClient.getAlert(selectedAlertIds.get(0)); } catch (ClientException e) { alertThrowable(this, e); return; } if (alert == null) { JOptionPane.showMessageDialog(Frame.this, "Alert no longer exists."); doRefreshAlerts(true); } else { ObjectXMLSerializer serializer = ObjectXMLSerializer.getInstance(); String alertXML = serializer.serialize(alert); exportFile(alertXML, alert.getName(), "XML", "Alert"); } } public void doExportAlerts() { JFileChooser exportFileChooser = new JFileChooser(); exportFileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); File currentDir = new File(userPreferences.get("currentDirectory", "")); if (currentDir.exists()) { exportFileChooser.setCurrentDirectory(currentDir); } int returnVal = exportFileChooser.showSaveDialog(this); File exportFile = null; File exportDirectory = null; if (returnVal == JFileChooser.APPROVE_OPTION) { userPreferences.put("currentDirectory", exportFileChooser.getCurrentDirectory().getPath()); try { exportDirectory = exportFileChooser.getSelectedFile(); List<AlertModel> alerts; try { alerts = mirthClient.getAllAlerts(); } catch (ClientException e) { alertThrowable(this, e); return; } for (AlertModel alert : alerts) { ObjectXMLSerializer serializer = ObjectXMLSerializer.getInstance(); String channelXML = serializer.serialize(alert); exportFile = new File(exportDirectory.getAbsolutePath() + "/" + alert.getName() + ".xml"); if (exportFile.exists()) { if (!alertOption(this, "The file " + alert.getName() + ".xml already exists. Would you like to overwrite it?")) { continue; } } FileUtils.writeStringToFile(exportFile, channelXML, UIConstants.CHARSET); } alertInformation(this, "All files were written successfully to " + exportDirectory.getPath() + "."); } catch (IOException ex) { alertError(this, "File could not be written."); } } } public void doImportAlert() { String content = browseForFileString("XML"); if (content != null) { importAlert(content, true); } } public void importAlert(String alertXML, boolean showAlerts) { ObjectXMLSerializer serializer = ObjectXMLSerializer.getInstance(); List<AlertModel> alertList; try { alertList = (List<AlertModel>) serializer.deserializeList( alertXML.replaceAll("\\&\\#x0D;\\n", "\n").replaceAll("\\&\\#x0D;", "\n"), AlertModel.class); } catch (Exception e) { if (showAlerts) { alertThrowable(this, e, "Invalid alert file:\n" + e.getMessage()); } return; } removeInvalidItems(alertList, AlertModel.class); for (AlertModel importAlert : alertList) { try { String alertName = importAlert.getName(); String tempId = mirthClient.getGuid(); // Check to see that the alert name doesn't already exist. if (!checkAlertName(alertName)) { if (!alertOption(this, "Would you like to overwrite the existing alert? Choose 'No' to create a new alert.")) { do { alertName = JOptionPane.showInputDialog(this, "Please enter a new name for the channel.", alertName); if (alertName == null) { return; } } while (!checkAlertName(alertName)); importAlert.setName(alertName); importAlert.setId(tempId); } else { for (Entry<String, String> entry : alertPanel.getAlertNames().entrySet()) { String id = entry.getKey(); String name = entry.getValue(); if (name.equalsIgnoreCase(alertName)) { // If overwriting, use the old id importAlert.setId(id); } } } } mirthClient.updateAlert(importAlert); } catch (Exception e) { alertThrowable(this, e, "Error importing alert:\n" + e.getMessage()); } } doRefreshAlerts(true); } /** * Checks to see if the passed in channel name already exists */ public boolean checkAlertName(String name) { if (name.equals("")) { alertWarning(this, "Alert name cannot be empty."); return false; } Pattern alphaNumericPattern = Pattern.compile("^[a-zA-Z_0-9\\-\\s]*$"); Matcher matcher = alphaNumericPattern.matcher(name); if (!matcher.find()) { alertWarning(this, "Alert name cannot have special characters besides hyphen, underscore, and space."); return false; } for (String alertName : alertPanel.getAlertNames().values()) { if (alertName.equalsIgnoreCase(name)) { alertWarning(this, "Alert \"" + name + "\" already exists."); return false; } } return true; } ///// Start Extension Tasks ///// public void doRefreshExtensions() { final String workingId = startWorking("Loading extension settings..."); if (confirmLeave()) { refreshExtensions(); } stopWorking(workingId); } public void refreshExtensions() { extensionsPanel.setPluginData(getPluginMetaData()); extensionsPanel.setConnectorData(getConnectorMetaData()); } public void doEnableExtension() { final String workingId = startWorking("Enabling extension..."); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { private boolean success = true; public Void doInBackground() { try { mirthClient.setExtensionEnabled(extensionsPanel.getSelectedExtension().getName(), true); } catch (ClientException e) { success = false; alertThrowable(PlatformUI.MIRTH_FRAME, e); } return null; } public void done() { if (success) { extensionsPanel.setSelectedExtensionEnabled(true); extensionsPanel.setRestartRequired(true); } stopWorking(workingId); } }; worker.execute(); } public void doDisableExtension() { final String workingId = startWorking("Disabling extension..."); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { private boolean success = true; public Void doInBackground() { try { mirthClient.setExtensionEnabled(extensionsPanel.getSelectedExtension().getName(), false); } catch (ClientException e) { success = false; alertThrowable(PlatformUI.MIRTH_FRAME, e); } return null; } public void done() { if (success) { extensionsPanel.setSelectedExtensionEnabled(false); extensionsPanel.setRestartRequired(true); } stopWorking(workingId); } }; worker.execute(); } public void doShowExtensionProperties() { extensionsPanel.showExtensionProperties(); } public void doUninstallExtension() { final String workingId = startWorking("Uninstalling extension..."); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { private boolean success = true; public Void doInBackground() { String packageName = extensionsPanel.getSelectedExtension().getPath(); if (alertOkCancel(PlatformUI.MIRTH_FRAME, "Uninstalling this extension will remove all plugins and/or connectors\nin the following extension folder: " + packageName)) { try { mirthClient.uninstallExtension(packageName); } catch (ClientException e) { success = false; alertThrowable(PlatformUI.MIRTH_FRAME, e); } } return null; } public void done() { if (success) { extensionsPanel.setRestartRequired(true); } stopWorking(workingId); } }; worker.execute(); } public boolean installExtension(File file) { try { if (file.exists()) { mirthClient.installExtension(file); } else { alertError(this, "Invalid extension file."); return false; } } catch (ClientException e) { if (e.getCause() != null && e.getCause() instanceof VersionMismatchException) { alertError(this, e.getCause().getMessage()); } else { alertThrowable(this, e, "Unable to install extension: " + e.getMessage()); } return false; } return true; } ///// End Extension Tasks ///// public boolean exportChannelOnError() { if (isSaveEnabled()) { int option = JOptionPane.showConfirmDialog(this, "Would you like to save the channel changes locally to your computer?"); if (option == JOptionPane.YES_OPTION) { if (!channelEditPanel.saveChanges()) { return false; } boolean enabled = isSaveEnabled(); setSaveEnabled(false); if (!doExportChannel()) { setSaveEnabled(enabled); return false; } } else if (option == JOptionPane.CANCEL_OPTION || option == JOptionPane.CLOSED_OPTION) { return false; } else { setSaveEnabled(false); } } return true; } public void setCanSave(boolean canSave) { this.canSave = canSave; } public void doContextSensitiveSave() { if (canSave) { if (currentContentPage == channelPanel) { channelPanel.doContextSensitiveSave(); } else if (currentContentPage == channelEditPanel) { doSaveChannel(); } else if (currentContentPage == channelEditPanel.filterPane) { doSaveChannel(); } else if (currentContentPage == channelEditPanel.transformerPane) { doSaveChannel(); } else if (currentContentPage == globalScriptsPanel) { doSaveGlobalScripts(); } else if (currentContentPage == codeTemplatePanel) { codeTemplatePanel.doContextSensitiveSave(); } else if (currentContentPage == settingsPane) { settingsPane.getCurrentSettingsPanel().doSave(); } else if (currentContentPage == alertEditPanel) { doSaveAlerts(); } } } public void doFind(JEditTextArea text) { FindRplDialog find; Window owner = getWindowForComponent(text); if (owner instanceof java.awt.Frame) { find = new FindRplDialog((java.awt.Frame) owner, true, text); } else { // window instanceof Dialog find = new FindRplDialog((java.awt.Dialog) owner, true, text); } find.setVisible(true); } public void doHelp() { BareBonesBrowserLaunch.openURL(UIConstants.HELP_LOCATION); } public void goToNotifications() { new NotificationDialog(); } public Map<String, PluginMetaData> getPluginMetaData() { return this.loadedPlugins; } public Map<String, ConnectorMetaData> getConnectorMetaData() { return this.loadedConnectors; } public String getSelectedChannelIdFromDashboard() { return dashboardPanel.getSelectedStatuses().get(0).getChannelId(); } public List<Integer> getSelectedMetaDataIdsFromDashboard(String channelId) { List<DashboardStatus> selectedStatuses = dashboardPanel.getSelectedStatuses(); List<Integer> metaDataIds = new ArrayList<Integer>(); if (selectedStatuses.size() == 0) { return metaDataIds; } for (DashboardStatus status : selectedStatuses) { if (status.getChannelId() == channelId) { Integer metaDataId = status.getMetaDataId(); if (metaDataId != null) { metaDataIds.add(metaDataId); } } } return metaDataIds; } public void retrieveUsers() throws ClientException { users = mirthClient.getAllUsers(); } public synchronized void updateAcceleratorKeyPressed(InputEvent e) { this.acceleratorKeyPressed = (((e.getModifiers() & Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()) > 0) || ((e.getModifiers() & InputEvent.CTRL_MASK) > 0) || ((e.getModifiers() & InputEvent.ALT_MASK) > 0)); } public synchronized boolean isAcceleratorKeyPressed() { return acceleratorKeyPressed; } /** * Checks to see if the passed in channel name already exists */ public boolean checkChannelName(String name, String id) { if (name.equals("")) { alertWarning(this, "Channel name cannot be empty."); return false; } if (name.length() > 40) { alertWarning(this, "Channel name cannot be longer than 40 characters."); return false; } Pattern alphaNumericPattern = Pattern.compile("^[a-zA-Z_0-9\\-\\s]*$"); Matcher matcher = alphaNumericPattern.matcher(name); if (!matcher.find()) { alertWarning(this, "Channel name cannot have special characters besides hyphen, underscore, and space."); return false; } for (ChannelStatus channelStatus : channelPanel.getCachedChannelStatuses().values()) { if (channelStatus.getChannel().getName().equalsIgnoreCase(name) && !channelStatus.getChannel().getId().equals(id)) { alertWarning(this, "Channel \"" + name + "\" already exists."); return false; } } return true; } public ChannelTagInfo getChannelTagInfo(boolean deployed) { ChannelTagInfo channelTagInfo = deployed ? deployedChannelTagInfo : this.channelTagInfo; synchronized (channelTagInfo) { return new ChannelTagInfo(channelTagInfo); } } public void setFilteredChannelTags(boolean deployed, Set<String> visibleTags, boolean enabled) { ChannelTagInfo channelTagInfo = deployed ? deployedChannelTagInfo : this.channelTagInfo; synchronized (channelTagInfo) { channelTagInfo.setVisibleTags(visibleTags); channelTagInfo.setEnabled(enabled); } } public void updateChannelTags(boolean deployed) { ChannelTagInfo channelTagInfo; Set<String> tags = new HashSet<String>(); if (deployed) { channelTagInfo = deployedChannelTagInfo; for (DashboardStatus dashboardStatus : status) { tags.addAll(dashboardStatus.getTags()); } } else { channelTagInfo = this.channelTagInfo; for (ChannelStatus channelStatus : channelPanel.getCachedChannelStatuses().values()) { tags.addAll(channelStatus.getChannel().getExportData().getMetadata().getTags()); } } synchronized (channelTagInfo) { channelTagInfo.setTags(tags); } } /** * Checks to see if the serialized object version is current, and prompts the user if it is not. */ public boolean promptObjectMigration(String content, String objectName) { String version = null; try { version = MigrationUtil.normalizeVersion(MigrationUtil.getSerializedObjectVersion(content), 3); } catch (Exception e) { logger.error("Failed to read version information", e); } StringBuilder message = new StringBuilder(); if (version == null) { message.append("The " + objectName + " being imported is from an older or unknown version of Mirth Connect.\n"); } else { int comparison = MigrationUtil.compareVersions(version, PlatformUI.SERVER_VERSION); if (comparison == 0) { return true; } if (comparison > 0) { alertInformation(this, "The " + objectName + " being imported originated from Mirth version " + version + ".\nYou are using Mirth Connect version " + PlatformUI.SERVER_VERSION + ".\nThe " + objectName + " cannot be imported, because it originated from a newer version of Mirth Connect."); return false; } if (comparison < 0) { message.append( "The " + objectName + " being imported originated from Mirth version " + version + ".\n"); } } message.append("You are using Mirth Connect version " + PlatformUI.SERVER_VERSION + ".\nWould you like to automatically convert the " + objectName + " to the " + PlatformUI.SERVER_VERSION + " format?"); return JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(this, message.toString(), "Select an Option", JOptionPane.YES_NO_OPTION); } /** * Removes items from the list that are not of the expected class. */ public void removeInvalidItems(List<?> list, Class<?> expectedClass) { if (list == null) { return; } int originalSize = list.size(); for (int i = 0; i < list.size(); i++) { if (!expectedClass.isInstance(list.get(i))) { list.remove(i--); } } if (list.size() < originalSize) { if (list.size() == 0) { alertError(this, "The imported object(s) are not of the expected class: " + expectedClass.getSimpleName()); } else { alertError(this, "One or more imported objects were skipped, because they are not of the expected class: " + expectedClass.getSimpleName()); } } } public List<ResourceProperties> getResources() { if (settingsPane == null) { settingsPane = new SettingsPane(); } SettingsPanelResources resourcesPanel = (SettingsPanelResources) settingsPane .getSettingsPanel(SettingsPanelResources.TAB_NAME); List<ResourceProperties> resourceProperties = resourcesPanel.getCachedResources(); if (resourceProperties == null) { resourcesPanel.refresh(); resourceProperties = resourcesPanel.getCachedResources(); } return resourceProperties; } public void updateResourceNames(Channel channel) { updateResourceNames(channel, getResources()); } public void updateResourceNames(Channel channel, List<ResourceProperties> resourceProperties) { if (!(channel instanceof InvalidChannel)) { updateResourceNames(channel.getProperties().getResourceIds(), resourceProperties); updateResourceNames(channel.getSourceConnector(), resourceProperties); for (Connector destinationConnector : channel.getDestinationConnectors()) { updateResourceNames(destinationConnector, resourceProperties); } } } public void updateResourceNames(Connector connector) { updateResourceNames(connector, getResources()); } private void updateResourceNames(Connector connector, List<ResourceProperties> resourceProperties) { if (connector.getProperties() instanceof SourceConnectorPropertiesInterface) { updateResourceNames(((SourceConnectorPropertiesInterface) connector.getProperties()) .getSourceConnectorProperties().getResourceIds(), resourceProperties); } else { updateResourceNames(((DestinationConnectorPropertiesInterface) connector.getProperties()) .getDestinationConnectorProperties().getResourceIds(), resourceProperties); } } private void updateResourceNames(Map<String, String> resourceIds, List<ResourceProperties> resourceProperties) { if (resourceProperties != null) { Set<String> invalidIds = new HashSet<String>(resourceIds.keySet()); // First update the names of all resources currently in the map for (ResourceProperties resource : resourceProperties) { if (resourceIds.containsKey(resource.getId())) { resourceIds.put(resource.getId(), resource.getName()); // If the resource ID was found it's not invalid invalidIds.remove(resource.getId()); } } /* * Iterate through all resource IDs that weren't found in the current list of resources. * If there's a resource with a different ID but the same name as a particular entry, * then replace the entry with the correct ID/name. */ for (String invalidId : invalidIds) { String resourceName = resourceIds.get(invalidId); if (StringUtils.isNotBlank(resourceName)) { for (ResourceProperties resource : resourceProperties) { // Replace if the names are equal and the resource ID isn't already contained in the map if (resource.getName().equals(resourceName) && !resourceIds.containsKey(resource.getId())) { resourceIds.put(resource.getId(), resourceName); resourceIds.remove(invalidId); } } } } } } }