From eda8cb286354d02a4eab220bf634022be2a9302f Mon Sep 17 00:00:00 2001 From: Uwe Stieber Date: Tue, 16 Apr 2013 13:30:59 +0200 Subject: Target Explorer: Network port can be an "auto-port" --- .../tcf/te/tcf/ui/controls/TcpTransportPanel.java | 14 + .../tcf/ui/editor/sections/TransportSection.java | 1340 ++++++++++---------- 2 files changed, 683 insertions(+), 671 deletions(-) (limited to 'target_explorer/plugins/org.eclipse.tcf.te.tcf.ui/src/org/eclipse/tcf') diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.ui/src/org/eclipse/tcf/te/tcf/ui/controls/TcpTransportPanel.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.ui/src/org/eclipse/tcf/te/tcf/ui/controls/TcpTransportPanel.java index 7bf237e80..634b1a83a 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.ui/src/org/eclipse/tcf/te/tcf/ui/controls/TcpTransportPanel.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.ui/src/org/eclipse/tcf/te/tcf/ui/controls/TcpTransportPanel.java @@ -14,6 +14,7 @@ import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.TypedEvent; import org.eclipse.tcf.protocol.IPeer; +import org.eclipse.tcf.te.core.nodes.interfaces.wire.IWireTypeNetwork; import org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer; import org.eclipse.tcf.te.tcf.ui.nls.Messages; import org.eclipse.tcf.te.ui.controls.BaseDialogPageControl; @@ -139,6 +140,9 @@ public class TcpTransportPanel extends NetworkCablePanel { if (port != null) isDirty |= !port.equals(data.getStringProperty(IPeer.ATTR_IP_PORT)); } + boolean autoPort = data.getBooleanProperty(IWireTypeNetwork.PROPERTY_NETWORK_PORT_IS_AUTO); + isDirty |= isAutoPort() != autoPort; + return isDirty; } @@ -158,6 +162,8 @@ public class TcpTransportPanel extends NetworkCablePanel { if (portControl != null) { portControl.setEditFieldControlText(data.getStringProperty(IPeer.ATTR_IP_PORT)); } + + setIsAutoPort(data.getBooleanProperty(IWireTypeNetwork.PROPERTY_NETWORK_PORT_IS_AUTO)); } /* (non-Javadoc) @@ -178,6 +184,12 @@ public class TcpTransportPanel extends NetworkCablePanel { String port = portControl.getEditFieldControlText(); data.setProperty(IPeer.ATTR_IP_PORT, !"".equals(port) ? port : null); //$NON-NLS-1$ } + + if (isAutoPort()) { + data.setProperty(IWireTypeNetwork.PROPERTY_NETWORK_PORT_IS_AUTO, Boolean.TRUE.toString()); + } else { + data.setProperty(IWireTypeNetwork.PROPERTY_NETWORK_PORT_IS_AUTO, null); + } } /* (non-Javadoc) @@ -188,6 +200,7 @@ public class TcpTransportPanel extends NetworkCablePanel { if (data == null) return; data.setProperty(IPeer.ATTR_IP_HOST, null); data.setProperty(IPeer.ATTR_IP_PORT, null); + data.setProperty(IWireTypeNetwork.PROPERTY_NETWORK_PORT_IS_AUTO, null); } /* (non-Javadoc) @@ -199,5 +212,6 @@ public class TcpTransportPanel extends NetworkCablePanel { Assert.isNotNull(dst); dst.setProperty(IPeer.ATTR_IP_HOST, src.getStringProperty(IPeer.ATTR_IP_HOST)); dst.setProperty(IPeer.ATTR_IP_PORT, src.getStringProperty(IPeer.ATTR_IP_PORT)); + dst.setProperty(IWireTypeNetwork.PROPERTY_NETWORK_PORT_IS_AUTO, src.getStringProperty(IWireTypeNetwork.PROPERTY_NETWORK_PORT_IS_AUTO)); } } diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.ui/src/org/eclipse/tcf/te/tcf/ui/editor/sections/TransportSection.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.ui/src/org/eclipse/tcf/te/tcf/ui/editor/sections/TransportSection.java index 28773453c..ba41070da 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.ui/src/org/eclipse/tcf/te/tcf/ui/editor/sections/TransportSection.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.ui/src/org/eclipse/tcf/te/tcf/ui/editor/sections/TransportSection.java @@ -1,671 +1,669 @@ -/******************************************************************************* - * Copyright (c) 2011, 2012 Wind River Systems, Inc. and others. All rights reserved. - * This program and the accompanying materials are made available under the terms - * of the Eclipse Public License v1.0 which accompanies this distribution, and is - * available at http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Wind River Systems - initial API and implementation - *******************************************************************************/ -package org.eclipse.tcf.te.tcf.ui.editor.sections; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; - -import org.eclipse.core.runtime.Assert; -import org.eclipse.jface.dialogs.IDialogSettings; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.TypedEvent; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.tcf.protocol.IChannel; -import org.eclipse.tcf.protocol.IPeer; -import org.eclipse.tcf.protocol.Protocol; -import org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer; -import org.eclipse.tcf.te.runtime.properties.PropertiesContainer; -import org.eclipse.tcf.te.tcf.core.Tcf; -import org.eclipse.tcf.te.tcf.core.interfaces.ITransportTypes; -import org.eclipse.tcf.te.tcf.core.peers.Peer; -import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel; -import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModelProperties; -import org.eclipse.tcf.te.tcf.locator.interfaces.services.ILocatorModelUpdateService; -import org.eclipse.tcf.te.tcf.locator.nodes.PeerRedirector; -import org.eclipse.tcf.te.tcf.ui.controls.CustomTransportPanel; -import org.eclipse.tcf.te.tcf.ui.controls.PipeTransportPanel; -import org.eclipse.tcf.te.tcf.ui.controls.TcpTransportPanel; -import org.eclipse.tcf.te.tcf.ui.editor.controls.TransportSectionTypeControl; -import org.eclipse.tcf.te.tcf.ui.editor.controls.TransportSectionTypePanelControl; -import org.eclipse.tcf.te.tcf.ui.nls.Messages; -import org.eclipse.tcf.te.ui.controls.interfaces.IWizardConfigurationPanel; -import org.eclipse.tcf.te.ui.forms.parts.AbstractSection; -import org.eclipse.tcf.te.ui.interfaces.data.IDataExchangeNode; -import org.eclipse.tcf.te.ui.interfaces.data.IDataExchangeNode3; -import org.eclipse.tcf.te.ui.swt.SWTControlUtil; -import org.eclipse.tcf.te.ui.views.editor.pages.AbstractEditorPage; -import org.eclipse.ui.forms.IManagedForm; -import org.eclipse.ui.forms.widgets.FormToolkit; -import org.eclipse.ui.forms.widgets.Section; - -/** - * Peer transport section implementation. - */ -public class TransportSection extends AbstractSection implements IDataExchangeNode { - // The section sub controls - private TransportSectionTypeControl transportTypeControl = null; - /* default */TransportSectionTypePanelControl transportTypePanelControl = null; - - // Reference to the original data object - protected IPeerModel od; - // Reference to a copy of the original data - /* default */final IPropertiesContainer odc = new PropertiesContainer(); - // Reference to the properties container representing the working copy for the section - /* default */final IPropertiesContainer wc = new PropertiesContainer(); - - /** - * Constructor. - * - * @param form The parent managed form. Must not be null. - * @param parent The parent composite. Must not be null. - */ - public TransportSection(IManagedForm form, Composite parent) { - super(form, parent, Section.DESCRIPTION); - createClient(getSection(), form.getToolkit()); - } - - /* - * (non-Javadoc) - * @see org.eclipse.ui.forms.AbstractFormPart#dispose() - */ - @Override - public void dispose() { - super.dispose(); - if (transportTypeControl != null) { - transportTypeControl.dispose(); - transportTypeControl = null; - } - if (transportTypePanelControl != null) { - transportTypePanelControl.dispose(); - transportTypePanelControl = null; - } - } - - /* - * (non-Javadoc) - * @see org.eclipse.tcf.te.ui.forms.parts.AbstractSection#getAdapter(java.lang.Class) - */ - @Override - public Object getAdapter(Class adapter) { - if (TransportSectionTypeControl.class.equals(adapter)) { - return transportTypeControl; - } - if (TransportSectionTypePanelControl.class.equals(adapter)) { - return transportTypePanelControl; - } - return super.getAdapter(adapter); - } - - /* - * (non-Javadoc) - * @see - * org.eclipse.tcf.te.ui.forms.parts.AbstractSection#createClient(org.eclipse.ui.forms.widgets - * .Section, org.eclipse.ui.forms.widgets.FormToolkit) - */ - @Override - protected void createClient(Section section, FormToolkit toolkit) { - Assert.isNotNull(section); - Assert.isNotNull(toolkit); - - // Configure the section - section.setText(Messages.TransportSection_title); - section.setDescription(Messages.TransportSection_description); - - if (section.getParent().getLayout() instanceof GridLayout) { - section.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); - } - - // Create the section client - Composite client = createClientContainer(section, 2, toolkit); - Assert.isNotNull(client); - section.setClient(client); - - // Create the transport type control - transportTypeControl = new TransportSectionTypeControl(this) { - @Override - public String[] getTransportTypes() { - List types = new ArrayList(); - for (String type : super.getTransportTypes()) { - if (isTransportTypeSupported(type)) { - types.add(type); - } - } - return types.toArray(new String[types.size()]); - } - }; - transportTypeControl.setFormToolkit(toolkit); - transportTypeControl.setAdjustBackgroundColor(true); - transportTypeControl.setupPanel(client); - - createEmptySpace(client, 2, toolkit); - - // The transport type specific controls are placed into a stack - transportTypePanelControl = new TransportSectionTypePanelControl(this); - - // Create and add the panels - if (isTransportTypeSupported(ITransportTypes.TRANSPORT_TYPE_TCP)) { - TcpTransportPanel tcpTransportPanel = new TcpTransportPanel(transportTypePanelControl) { - @Override - protected boolean isAdjustBackgroundColor() { - return true; - } - @Override - protected boolean hasHistory() { - return true; - } - }; - transportTypePanelControl.addConfigurationPanel(ITransportTypes.TRANSPORT_TYPE_TCP, tcpTransportPanel); - } - if (isTransportTypeSupported(ITransportTypes.TRANSPORT_TYPE_SSL)) { - TcpTransportPanel sslTransportPanel = new TcpTransportPanel(transportTypePanelControl) { - @Override - protected boolean isAdjustBackgroundColor() { - return true; - } - }; - transportTypePanelControl.addConfigurationPanel(ITransportTypes.TRANSPORT_TYPE_SSL, sslTransportPanel); - } - if (isTransportTypeSupported(ITransportTypes.TRANSPORT_TYPE_PIPE)) { - PipeTransportPanel pipeTransportPanle = new PipeTransportPanel(transportTypePanelControl) { - @Override - protected boolean isAdjustBackgroundColor() { - return true; - } - }; - transportTypePanelControl.addConfigurationPanel(ITransportTypes.TRANSPORT_TYPE_PIPE, pipeTransportPanle); - } - if (isTransportTypeSupported(ITransportTypes.TRANSPORT_TYPE_CUSTOM)) { - CustomTransportPanel customTransportPanel = new CustomTransportPanel(transportTypePanelControl) { - @Override - protected boolean isAdjustBackgroundColor() { - return true; - } - }; - transportTypePanelControl.addConfigurationPanel(ITransportTypes.TRANSPORT_TYPE_CUSTOM, customTransportPanel); - } - - // Setup the panel control - transportTypePanelControl.setupPanel(client, transportTypePanelControl.getConfigurationPanelIds(), toolkit); - GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true); - layoutData.horizontalSpan = 2; - transportTypePanelControl.getPanel().setLayoutData(layoutData); - toolkit.adapt(transportTypePanelControl.getPanel()); - - transportTypePanelControl.showConfigurationPanel(transportTypeControl - .getSelectedTransportType()); - - // Adjust the control enablement - updateEnablement(); - - // Mark the control update as completed now - setIsUpdating(false); - } - - /** - * Override to control the availability of transport types. - * - * @param transportType - * @return true if the given transport type should is available. - */ - public boolean isTransportTypeSupported(String transportType) { - return true; - } - - /** - * Indicates whether the sections parent page has become the active in the editor. - * - * @param active True if the parent page should be visible, false - * otherwise. - */ - public void setActive(boolean active) { - // If the parent page has become the active and it does not contain - // unsaved data, than fill in the data from the selected node - if (active) { - // Leave everything unchanged if the page is in dirty state - if (getManagedForm().getContainer() instanceof AbstractEditorPage && !((AbstractEditorPage) getManagedForm() - .getContainer()).isDirty()) { - Object node = ((AbstractEditorPage) getManagedForm().getContainer()) - .getEditorInputNode(); - if (node instanceof IPeerModel) { - setupData((IPeerModel) node); - } - } - } - else { - // Evaluate the dirty state even if going inactive - dataChanged(null); - } - } - - /* (non-Javadoc) - * @see org.eclipse.tcf.te.ui.interfaces.data.IDataExchangeNode#setupData(org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer) - */ - @Override - public void setupData(IPropertiesContainer data) { - Assert.isNotNull(data); - - // Mark the control update as in-progress now - setIsUpdating(true); - - if (transportTypeControl != null) { - String transportType = data.getStringProperty(IPeer.ATTR_TRANSPORT_NAME); - if (transportType != null && !"".equals(transportType)) { //$NON-NLS-1$ - transportTypeControl.setSelectedTransportType(transportType); - - if (transportTypePanelControl != null) { - transportTypePanelControl.showConfigurationPanel(transportType); - IWizardConfigurationPanel panel = transportTypePanelControl - .getConfigurationPanel(transportType); - if (panel instanceof IDataExchangeNode) { - ((IDataExchangeNode) panel).setupData(data); - } - } - } - } - - // Mark the control update as completed now - setIsUpdating(false); - // Re-evaluate the dirty state - dataChanged(null); - // Adjust the control enablement - updateEnablement(); - } - - /** - * Initialize the page widgets based of the data from the given peer node. - *

- * This method may called multiple times during the lifetime of the page and the given - * configuration node might be even null. - * - * @param node The peer node or null. - */ - public void setupData(final IPeerModel node) { - // If the section is dirty, nothing is changed - if (isDirty()) return; - - boolean updateWidgets = true; - - // If the passed in node is the same as the previous one, - // no need for updating the section widgets. - if ((node == null && od == null) || (node != null && node.equals(od))) { - updateWidgets = false; - } - - // Besides the node itself, we need to look at the node data to determine - // if the widgets needs to be updated. For the comparisation, keep the - // current properties of the original data copy in a temporary container. - final IPropertiesContainer previousOdc = new PropertiesContainer(); - previousOdc.setProperties(odc.getProperties()); - - // Store a reference to the original data - od = node; - // Clean the original data copy - odc.clearProperties(); - // Clean the working copy - wc.clearProperties(); - - // If no data is available, we are done - if (node == null) return; - - // Thread access to the model is limited to the executors thread. - // Copy the data over to the working copy to ease the access. - Protocol.invokeAndWait(new Runnable() { - @Override - public void run() { - // The section is handling the transport name and the - // transport type specific properties. Ignore other properties. - odc.setProperty(IPeer.ATTR_TRANSPORT_NAME, node.getPeer().getTransportName()); - if (transportTypePanelControl != null) { - IPropertiesContainer src = new PropertiesContainer(); - Map properties = node.getPeer().getAttributes(); - for (Entry entry : properties.entrySet()) { - src.setProperty(entry.getKey(), entry.getValue()); - } - - for (String id : transportTypePanelControl.getConfigurationPanelIds()) { - IWizardConfigurationPanel panel = transportTypePanelControl - .getConfigurationPanel(id); - if (panel instanceof IDataExchangeNode3) { - ((IDataExchangeNode3) panel).copyData(src, odc); - } - } - } - - // Initially, the working copy is a duplicate of the original data copy - wc.setProperties(odc.getProperties()); - } - }); - - // From here on, work with the working copy only! - - // If the original data copy does not match the previous original - // data copy, the widgets needs to be updated to present the correct data. - if (!previousOdc.getProperties().equals(odc.getProperties())) { - updateWidgets = true; - } - - if (updateWidgets) { - setupData(wc); - } - else { - // Re-evaluate the dirty state - dataChanged(null); - // Adjust the control enablement - updateEnablement(); - } - } - - /* (non-Javadoc) - * @see org.eclipse.tcf.te.ui.interfaces.data.IDataExchangeNode#extractData(org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer) - */ - @Override - public void extractData(IPropertiesContainer data) { - Assert.isNotNull(data); - - if (transportTypePanelControl != null) { - String[] ids = transportTypePanelControl.getConfigurationPanelIds(); - for (String id : ids) { - IWizardConfigurationPanel panel = transportTypePanelControl.getConfigurationPanel(id); - if (panel instanceof IDataExchangeNode) { - if (panel instanceof IDataExchangeNode3) { - ((IDataExchangeNode3) panel).removeData(data); - } - } - } - IWizardConfigurationPanel panel = transportTypePanelControl.getActiveConfigurationPanel(); - if (panel instanceof IDataExchangeNode) { - ((IDataExchangeNode) panel).extractData(data); - } - } - - if (transportTypeControl != null) { - data.setProperty(IPeer.ATTR_TRANSPORT_NAME, transportTypeControl - .getSelectedTransportType()); - } - } - - /** - * Stores the page widgets current values to the given peer node. - *

- * This method may called multiple times during the lifetime of the page and the given peer node - * might be even null. - * - * @param node The GDB Remote configuration node or null. - */ - public void extractData(final IPeerModel node) { - // If no data is available, we are done - if (node == null) { - return; - } - - // The list of removed attributes - final List removed = new ArrayList(); - // Get the current key set from the working copy - Set currentKeySet = wc.getProperties().keySet(); - - extractData(wc); - - // If the data has not changed compared to the original data copy, - // we are done here and return immediately - if (odc.equals(wc)) { - return; - } - - // Get the new key set from the working copy - Set newKeySet = wc.getProperties().keySet(); - // Everything from the old key set not found in the new key set is a removed attribute - for (String key : currentKeySet) { - if (!newKeySet.contains(key)) { - removed.add(key); - } - } - - // Copy the working copy data back to the original properties container - Protocol.invokeAndWait(new Runnable() { - @Override - public void run() { - // To update the peer attributes, the peer needs to be recreated - IPeer oldPeer = node.getPeer(); - // Create a write able copy of the peer attributes - Map attributes = new HashMap(oldPeer - .getAttributes()); - // Clean out the removed attributes - for (String key : removed) { - attributes.remove(key); - } - // Update with the current configured attributes - for (String key : wc.getProperties().keySet()) { - String value = wc.getStringProperty(key); - if (value != null) { - attributes.put(key, value); - } - else { - attributes.remove(key); - } - } - - // If there is still a open channel to the old peer, close it by force - IChannel channel = Tcf.getChannelManager().getChannel(oldPeer); - if (channel != null) { - channel.close(); - } - - // Create the new peer - IPeer newPeer = oldPeer instanceof PeerRedirector ? new PeerRedirector(((PeerRedirector) oldPeer) - .getParent(), attributes) : new Peer(attributes); - // Update the peer node instance (silently) - boolean changed = node.setChangeEventsEnabled(false); - node.setProperty(IPeerModelProperties.PROP_INSTANCE, newPeer); - // As the transport changed, we have to reset the state back to "unknown" - // and clear out the services and DNS markers - node.setProperty(IPeerModelProperties.PROP_STATE, IPeerModelProperties.STATE_UNKNOWN); - node.setProperty("dns.name.transient", null); //$NON-NLS-1$ - node.setProperty("dns.lastIP.transient", null); //$NON-NLS-1$ - node.setProperty("dns.skip.transient", null); //$NON-NLS-1$ - - ILocatorModelUpdateService service = node.getModel() - .getService(ILocatorModelUpdateService.class); - service.updatePeerServices(node, null, null); - - if (changed) { - node.setChangeEventsEnabled(true); - } - } - }); - } - - /* - * (non-Javadoc) - * @see org.eclipse.tcf.te.ui.forms.parts.AbstractSection#isValid() - */ - @Override - public boolean isValid() { - // Validation is skipped while the controls are updated - if (isUpdating()) return true; - - boolean valid = super.isValid(); - - if (transportTypeControl != null) { - valid &= transportTypeControl.isValid(); - if (transportTypeControl.getMessageType() > getMessageType()) { - setMessage(transportTypeControl.getMessage(), transportTypeControl.getMessageType()); - } - } - - if (transportTypePanelControl != null) { - valid &= transportTypePanelControl.isValid(); - if (transportTypePanelControl.getMessageType() > getMessageType()) { - setMessage(transportTypePanelControl.getMessage(), transportTypePanelControl.getMessageType()); - } - } - - return valid; - } - - /* - * (non-Javadoc) - * @see org.eclipse.ui.forms.AbstractFormPart#commit(boolean) - */ - @Override - public void commit(boolean onSave) { - // Remember the current dirty state - boolean needsSaving = isDirty(); - // Call the super implementation (resets the dirty state) - super.commit(onSave); - - // Nothing to do if not on save or saving is not needed - if (!onSave || !needsSaving) { - return; - } - // Extract the data into the original data node - extractData(od); - } - - /** - * Called to signal that the data associated has been changed. - * - * @param e The event which triggered the invocation or null. - */ - public void dataChanged(TypedEvent e) { - // dataChanged is not evaluated while the controls are updated - if (isUpdating()) return; - - boolean isDirty = false; - - if (transportTypeControl != null) { - String transportType = transportTypeControl.getSelectedTransportType(); - if ("".equals(transportType)) { //$NON-NLS-1$ - String value = odc.getStringProperty(IPeer.ATTR_TRANSPORT_NAME); - isDirty |= value != null && !"".equals(value.trim()); //$NON-NLS-1$ - } - else { - isDirty |= !odc.isProperty(IPeer.ATTR_TRANSPORT_NAME, transportType); - } - - if (transportTypePanelControl != null) { - IWizardConfigurationPanel panel = transportTypePanelControl - .getConfigurationPanel(transportType); - if (panel != null) { - isDirty |= panel.dataChanged(odc, e); - } - } - } - - // If dirty, mark the form part dirty. - // Otherwise call refresh() to reset the dirty (and stale) flag - markDirty(isDirty); - - // Adjust the control enablement - updateEnablement(); - } - - /** - * Updates the given set of attributes with the current values of the page widgets. - * - * @param attributes The attributes to update. Must not be null: - */ - public void updateAttributes(IPropertiesContainer attributes) { - Assert.isNotNull(attributes); - - if (transportTypePanelControl != null) { - String[] ids = transportTypePanelControl.getConfigurationPanelIds(); - for (String id : ids) { - IWizardConfigurationPanel panel = transportTypePanelControl.getConfigurationPanel(id); - if (panel instanceof IDataExchangeNode) { - if (panel instanceof IDataExchangeNode3) { - ((IDataExchangeNode3) panel).removeData(attributes); - } - } - } - IWizardConfigurationPanel panel = transportTypePanelControl.getActiveConfigurationPanel(); - if (panel instanceof IDataExchangeNode) { - ((IDataExchangeNode) panel).extractData(attributes); - } - } - - if (transportTypeControl != null) { - attributes.setProperty(IPeer.ATTR_TRANSPORT_NAME, transportTypeControl - .getSelectedTransportType()); - } - } - - /** - * Updates the control enablement. - */ - protected void updateEnablement() { - // Determine the input - final Object input = od; // getManagedForm().getInput(); - - // Determine if the peer is a static peer - final AtomicBoolean isStatic = new AtomicBoolean(); - final AtomicBoolean isRemote = new AtomicBoolean(); - Runnable runnable = new Runnable() { - @Override - public void run() { - if (input instanceof IPeerModel) { - isStatic.set(((IPeerModel) input).isStatic()); - isRemote.set(((IPeerModel) input).isRemote()); - } - } - }; - - if (Protocol.isDispatchThread()) runnable.run(); - else Protocol.invokeAndWait(runnable); - - // The transport type control is enabled for static peers - if (transportTypeControl != null) { - boolean enabled = !isReadOnly() && (input == null || (isStatic.get() && !isRemote.get())); - SWTControlUtil.setEnabled(transportTypeControl.getEditFieldControl(), enabled); - if (transportTypePanelControl != null) { - IWizardConfigurationPanel panel = transportTypePanelControl - .getConfigurationPanel(transportTypeControl - .getSelectedTransportType()); - if (panel != null) { - panel.setEnabled(enabled); - } - } - } - } - - /* (non-Javadoc) - * @see org.eclipse.tcf.te.ui.forms.parts.AbstractSection#saveWidgetValues(org.eclipse.jface.dialogs.IDialogSettings) - */ - @Override - public void saveWidgetValues(IDialogSettings settings) { - super.saveWidgetValues(settings); - - if (settings != null) { - if (transportTypePanelControl != null) { - transportTypePanelControl.saveWidgetValues(settings, TransportSection.class.getSimpleName()); - } - } - } - - /* (non-Javadoc) - * @see org.eclipse.tcf.te.ui.forms.parts.AbstractSection#restoreWidgetValues(org.eclipse.jface.dialogs.IDialogSettings) - */ - @Override - public void restoreWidgetValues(IDialogSettings settings) { - super.restoreWidgetValues(settings); - - if (settings != null) { - if (transportTypePanelControl != null) { - transportTypePanelControl.restoreWidgetValues(settings, TransportSection.class.getSimpleName()); - } - } - } -} +/******************************************************************************* + * Copyright (c) 2011, 2012 Wind River Systems, Inc. and others. All rights reserved. + * This program and the accompanying materials are made available under the terms + * of the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tcf.te.tcf.ui.editor.sections; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.TypedEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.tcf.protocol.IChannel; +import org.eclipse.tcf.protocol.IPeer; +import org.eclipse.tcf.protocol.Protocol; +import org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer; +import org.eclipse.tcf.te.runtime.properties.PropertiesContainer; +import org.eclipse.tcf.te.tcf.core.Tcf; +import org.eclipse.tcf.te.tcf.core.interfaces.ITransportTypes; +import org.eclipse.tcf.te.tcf.core.peers.Peer; +import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel; +import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModelProperties; +import org.eclipse.tcf.te.tcf.locator.interfaces.services.ILocatorModelUpdateService; +import org.eclipse.tcf.te.tcf.locator.nodes.PeerRedirector; +import org.eclipse.tcf.te.tcf.ui.controls.CustomTransportPanel; +import org.eclipse.tcf.te.tcf.ui.controls.PipeTransportPanel; +import org.eclipse.tcf.te.tcf.ui.controls.TcpTransportPanel; +import org.eclipse.tcf.te.tcf.ui.editor.controls.TransportSectionTypeControl; +import org.eclipse.tcf.te.tcf.ui.editor.controls.TransportSectionTypePanelControl; +import org.eclipse.tcf.te.tcf.ui.nls.Messages; +import org.eclipse.tcf.te.ui.controls.interfaces.IWizardConfigurationPanel; +import org.eclipse.tcf.te.ui.forms.parts.AbstractSection; +import org.eclipse.tcf.te.ui.interfaces.data.IDataExchangeNode; +import org.eclipse.tcf.te.ui.interfaces.data.IDataExchangeNode3; +import org.eclipse.tcf.te.ui.swt.SWTControlUtil; +import org.eclipse.tcf.te.ui.views.editor.pages.AbstractEditorPage; +import org.eclipse.ui.forms.IManagedForm; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.Section; + +/** + * Peer transport section implementation. + */ +public class TransportSection extends AbstractSection implements IDataExchangeNode { + // The section sub controls + private TransportSectionTypeControl transportTypeControl = null; + /* default */TransportSectionTypePanelControl transportTypePanelControl = null; + + // Reference to the original data object + protected IPeerModel od; + // Reference to a copy of the original data + /* default */final IPropertiesContainer odc = new PropertiesContainer(); + // Reference to the properties container representing the working copy for the section + /* default */final IPropertiesContainer wc = new PropertiesContainer(); + + /** + * Constructor. + * + * @param form The parent managed form. Must not be null. + * @param parent The parent composite. Must not be null. + */ + public TransportSection(IManagedForm form, Composite parent) { + super(form, parent, Section.DESCRIPTION); + createClient(getSection(), form.getToolkit()); + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.forms.AbstractFormPart#dispose() + */ + @Override + public void dispose() { + super.dispose(); + if (transportTypeControl != null) { + transportTypeControl.dispose(); + transportTypeControl = null; + } + if (transportTypePanelControl != null) { + transportTypePanelControl.dispose(); + transportTypePanelControl = null; + } + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.forms.parts.AbstractSection#getAdapter(java.lang.Class) + */ + @Override + public Object getAdapter(Class adapter) { + if (TransportSectionTypeControl.class.equals(adapter)) { + return transportTypeControl; + } + if (TransportSectionTypePanelControl.class.equals(adapter)) { + return transportTypePanelControl; + } + return super.getAdapter(adapter); + } + + /* + * (non-Javadoc) + * @see + * org.eclipse.tcf.te.ui.forms.parts.AbstractSection#createClient(org.eclipse.ui.forms.widgets + * .Section, org.eclipse.ui.forms.widgets.FormToolkit) + */ + @Override + protected void createClient(Section section, FormToolkit toolkit) { + Assert.isNotNull(section); + Assert.isNotNull(toolkit); + + // Configure the section + section.setText(Messages.TransportSection_title); + section.setDescription(Messages.TransportSection_description); + + if (section.getParent().getLayout() instanceof GridLayout) { + section.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + } + + // Create the section client + Composite client = createClientContainer(section, 2, toolkit); + Assert.isNotNull(client); + section.setClient(client); + + // Create the transport type control + transportTypeControl = new TransportSectionTypeControl(this) { + @Override + public String[] getTransportTypes() { + List types = new ArrayList(); + for (String type : super.getTransportTypes()) { + if (isTransportTypeSupported(type)) { + types.add(type); + } + } + return types.toArray(new String[types.size()]); + } + }; + transportTypeControl.setFormToolkit(toolkit); + transportTypeControl.setAdjustBackgroundColor(true); + transportTypeControl.setupPanel(client); + + createEmptySpace(client, 2, toolkit); + + // The transport type specific controls are placed into a stack + transportTypePanelControl = new TransportSectionTypePanelControl(this); + + // Create and add the panels + if (isTransportTypeSupported(ITransportTypes.TRANSPORT_TYPE_TCP)) { + TcpTransportPanel tcpTransportPanel = new TcpTransportPanel(transportTypePanelControl) { + @Override + protected boolean isAdjustBackgroundColor() { + return true; + } + @Override + protected boolean hasHistory() { + return true; + } + }; + transportTypePanelControl.addConfigurationPanel(ITransportTypes.TRANSPORT_TYPE_TCP, tcpTransportPanel); + } + if (isTransportTypeSupported(ITransportTypes.TRANSPORT_TYPE_SSL)) { + TcpTransportPanel sslTransportPanel = new TcpTransportPanel(transportTypePanelControl) { + @Override + protected boolean isAdjustBackgroundColor() { + return true; + } + }; + transportTypePanelControl.addConfigurationPanel(ITransportTypes.TRANSPORT_TYPE_SSL, sslTransportPanel); + } + if (isTransportTypeSupported(ITransportTypes.TRANSPORT_TYPE_PIPE)) { + PipeTransportPanel pipeTransportPanle = new PipeTransportPanel(transportTypePanelControl) { + @Override + protected boolean isAdjustBackgroundColor() { + return true; + } + }; + transportTypePanelControl.addConfigurationPanel(ITransportTypes.TRANSPORT_TYPE_PIPE, pipeTransportPanle); + } + if (isTransportTypeSupported(ITransportTypes.TRANSPORT_TYPE_CUSTOM)) { + CustomTransportPanel customTransportPanel = new CustomTransportPanel(transportTypePanelControl) { + @Override + protected boolean isAdjustBackgroundColor() { + return true; + } + }; + transportTypePanelControl.addConfigurationPanel(ITransportTypes.TRANSPORT_TYPE_CUSTOM, customTransportPanel); + } + + // Setup the panel control + transportTypePanelControl.setupPanel(client, transportTypePanelControl.getConfigurationPanelIds(), toolkit); + GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true); + layoutData.horizontalSpan = 2; + transportTypePanelControl.getPanel().setLayoutData(layoutData); + toolkit.adapt(transportTypePanelControl.getPanel()); + + transportTypePanelControl.showConfigurationPanel(transportTypeControl + .getSelectedTransportType()); + + // Adjust the control enablement + updateEnablement(); + + // Mark the control update as completed now + setIsUpdating(false); + } + + /** + * Override to control the availability of transport types. + * + * @param transportType + * @return true if the given transport type should is available. + */ + public boolean isTransportTypeSupported(String transportType) { + return true; + } + + /** + * Indicates whether the sections parent page has become the active in the editor. + * + * @param active True if the parent page should be visible, false + * otherwise. + */ + public void setActive(boolean active) { + // If the parent page has become the active and it does not contain + // unsaved data, than fill in the data from the selected node + if (active) { + // Leave everything unchanged if the page is in dirty state + if (getManagedForm().getContainer() instanceof AbstractEditorPage && !((AbstractEditorPage) getManagedForm() + .getContainer()).isDirty()) { + Object node = ((AbstractEditorPage) getManagedForm().getContainer()) + .getEditorInputNode(); + if (node instanceof IPeerModel) { + setupData((IPeerModel) node); + } + } + } + else { + // Evaluate the dirty state even if going inactive + dataChanged(null); + } + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.ui.interfaces.data.IDataExchangeNode#setupData(org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer) + */ + @Override + public void setupData(IPropertiesContainer data) { + Assert.isNotNull(data); + + // Mark the control update as in-progress now + setIsUpdating(true); + + if (transportTypeControl != null) { + String transportType = data.getStringProperty(IPeer.ATTR_TRANSPORT_NAME); + if (transportType != null && !"".equals(transportType)) { //$NON-NLS-1$ + transportTypeControl.setSelectedTransportType(transportType); + + if (transportTypePanelControl != null) { + transportTypePanelControl.showConfigurationPanel(transportType); + IWizardConfigurationPanel panel = transportTypePanelControl.getConfigurationPanel(transportType); + if (panel instanceof IDataExchangeNode) { + ((IDataExchangeNode) panel).setupData(data); + } + } + } + } + + // Mark the control update as completed now + setIsUpdating(false); + // Re-evaluate the dirty state + dataChanged(null); + // Adjust the control enablement + updateEnablement(); + } + + /** + * Initialize the page widgets based of the data from the given peer node. + *

+ * This method may called multiple times during the lifetime of the page and the given + * configuration node might be even null. + * + * @param node The peer node or null. + */ + public void setupData(final IPeerModel node) { + // If the section is dirty, nothing is changed + if (isDirty()) return; + + boolean updateWidgets = true; + + // If the passed in node is the same as the previous one, + // no need for updating the section widgets. + if ((node == null && od == null) || (node != null && node.equals(od))) { + updateWidgets = false; + } + + // Besides the node itself, we need to look at the node data to determine + // if the widgets needs to be updated. For the comparisation, keep the + // current properties of the original data copy in a temporary container. + final IPropertiesContainer previousOdc = new PropertiesContainer(); + previousOdc.setProperties(odc.getProperties()); + + // Store a reference to the original data + od = node; + // Clean the original data copy + odc.clearProperties(); + // Clean the working copy + wc.clearProperties(); + + // If no data is available, we are done + if (node == null) return; + + // Thread access to the model is limited to the executors thread. + // Copy the data over to the working copy to ease the access. + Protocol.invokeAndWait(new Runnable() { + @Override + public void run() { + // The section is handling the transport name and the + // transport type specific properties. Ignore other properties. + odc.setProperty(IPeer.ATTR_TRANSPORT_NAME, node.getPeer().getTransportName()); + if (transportTypePanelControl != null) { + IPropertiesContainer src = new PropertiesContainer(); + Map properties = node.getPeer().getAttributes(); + for (Entry entry : properties.entrySet()) { + src.setProperty(entry.getKey(), entry.getValue()); + } + + for (String id : transportTypePanelControl.getConfigurationPanelIds()) { + IWizardConfigurationPanel panel = transportTypePanelControl + .getConfigurationPanel(id); + if (panel instanceof IDataExchangeNode3) { + ((IDataExchangeNode3) panel).copyData(src, odc); + } + } + } + + // Initially, the working copy is a duplicate of the original data copy + wc.setProperties(odc.getProperties()); + } + }); + + // From here on, work with the working copy only! + + // If the original data copy does not match the previous original + // data copy, the widgets needs to be updated to present the correct data. + if (!previousOdc.getProperties().equals(odc.getProperties())) { + updateWidgets = true; + } + + if (updateWidgets) { + setupData(wc); + } + else { + // Re-evaluate the dirty state + dataChanged(null); + // Adjust the control enablement + updateEnablement(); + } + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.ui.interfaces.data.IDataExchangeNode#extractData(org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer) + */ + @Override + public void extractData(IPropertiesContainer data) { + Assert.isNotNull(data); + + if (transportTypePanelControl != null) { + String[] ids = transportTypePanelControl.getConfigurationPanelIds(); + for (String id : ids) { + IWizardConfigurationPanel panel = transportTypePanelControl.getConfigurationPanel(id); + if (panel instanceof IDataExchangeNode) { + if (panel instanceof IDataExchangeNode3) { + ((IDataExchangeNode3) panel).removeData(data); + } + } + } + IWizardConfigurationPanel panel = transportTypePanelControl.getActiveConfigurationPanel(); + if (panel instanceof IDataExchangeNode) { + ((IDataExchangeNode) panel).extractData(data); + } + } + + if (transportTypeControl != null) { + data.setProperty(IPeer.ATTR_TRANSPORT_NAME, transportTypeControl + .getSelectedTransportType()); + } + } + + /** + * Stores the page widgets current values to the given peer node. + *

+ * This method may called multiple times during the lifetime of the page and the given peer node + * might be even null. + * + * @param node The GDB Remote configuration node or null. + */ + public void extractData(final IPeerModel node) { + // If no data is available, we are done + if (node == null) { + return; + } + + // The list of removed attributes + final List removed = new ArrayList(); + // Get the current key set from the working copy + Set currentKeySet = wc.getProperties().keySet(); + + extractData(wc); + + // If the data has not changed compared to the original data copy, + // we are done here and return immediately + if (odc.equals(wc)) { + return; + } + + // Get the new key set from the working copy + Set newKeySet = wc.getProperties().keySet(); + // Everything from the old key set not found in the new key set is a removed attribute + for (String key : currentKeySet) { + if (!newKeySet.contains(key)) { + removed.add(key); + } + } + + // Copy the working copy data back to the original properties container + Protocol.invokeAndWait(new Runnable() { + @Override + public void run() { + // To update the peer attributes, the peer needs to be recreated + IPeer oldPeer = node.getPeer(); + // Create a write able copy of the peer attributes + Map attributes = new HashMap(oldPeer + .getAttributes()); + // Clean out the removed attributes + for (String key : removed) { + attributes.remove(key); + } + // Update with the current configured attributes + for (String key : wc.getProperties().keySet()) { + String value = wc.getStringProperty(key); + if (value != null) { + attributes.put(key, value); + } + else { + attributes.remove(key); + } + } + + // If there is still a open channel to the old peer, close it by force + IChannel channel = Tcf.getChannelManager().getChannel(oldPeer); + if (channel != null) { + channel.close(); + } + + // Create the new peer + IPeer newPeer = oldPeer instanceof PeerRedirector ? new PeerRedirector(((PeerRedirector) oldPeer) + .getParent(), attributes) : new Peer(attributes); + // Update the peer node instance (silently) + boolean changed = node.setChangeEventsEnabled(false); + node.setProperty(IPeerModelProperties.PROP_INSTANCE, newPeer); + // As the transport changed, we have to reset the state back to "unknown" + // and clear out the services and DNS markers + node.setProperty(IPeerModelProperties.PROP_STATE, IPeerModelProperties.STATE_UNKNOWN); + node.setProperty("dns.name.transient", null); //$NON-NLS-1$ + node.setProperty("dns.lastIP.transient", null); //$NON-NLS-1$ + node.setProperty("dns.skip.transient", null); //$NON-NLS-1$ + + ILocatorModelUpdateService service = node.getModel() + .getService(ILocatorModelUpdateService.class); + service.updatePeerServices(node, null, null); + + if (changed) { + node.setChangeEventsEnabled(true); + } + } + }); + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.forms.parts.AbstractSection#isValid() + */ + @Override + public boolean isValid() { + // Validation is skipped while the controls are updated + if (isUpdating()) return true; + + boolean valid = super.isValid(); + + if (transportTypeControl != null) { + valid &= transportTypeControl.isValid(); + if (transportTypeControl.getMessageType() > getMessageType()) { + setMessage(transportTypeControl.getMessage(), transportTypeControl.getMessageType()); + } + } + + if (transportTypePanelControl != null) { + valid &= transportTypePanelControl.isValid(); + if (transportTypePanelControl.getMessageType() > getMessageType()) { + setMessage(transportTypePanelControl.getMessage(), transportTypePanelControl.getMessageType()); + } + } + + return valid; + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.forms.AbstractFormPart#commit(boolean) + */ + @Override + public void commit(boolean onSave) { + // Remember the current dirty state + boolean needsSaving = isDirty(); + // Call the super implementation (resets the dirty state) + super.commit(onSave); + + // Nothing to do if not on save or saving is not needed + if (!onSave || !needsSaving) { + return; + } + // Extract the data into the original data node + extractData(od); + } + + /** + * Called to signal that the data associated has been changed. + * + * @param e The event which triggered the invocation or null. + */ + public void dataChanged(TypedEvent e) { + // dataChanged is not evaluated while the controls are updated + if (isUpdating()) return; + + boolean isDirty = false; + + if (transportTypeControl != null) { + String transportType = transportTypeControl.getSelectedTransportType(); + if ("".equals(transportType)) { //$NON-NLS-1$ + String value = odc.getStringProperty(IPeer.ATTR_TRANSPORT_NAME); + isDirty |= value != null && !"".equals(value.trim()); //$NON-NLS-1$ + } + else { + isDirty |= !odc.isProperty(IPeer.ATTR_TRANSPORT_NAME, transportType); + } + + if (transportTypePanelControl != null) { + IWizardConfigurationPanel panel = transportTypePanelControl.getConfigurationPanel(transportType); + if (panel != null) { + isDirty |= panel.dataChanged(odc, e); + } + } + } + + // If dirty, mark the form part dirty. + // Otherwise call refresh() to reset the dirty (and stale) flag + markDirty(isDirty); + + // Adjust the control enablement + updateEnablement(); + } + + /** + * Updates the given set of attributes with the current values of the page widgets. + * + * @param attributes The attributes to update. Must not be null: + */ + public void updateAttributes(IPropertiesContainer attributes) { + Assert.isNotNull(attributes); + + if (transportTypePanelControl != null) { + String[] ids = transportTypePanelControl.getConfigurationPanelIds(); + for (String id : ids) { + IWizardConfigurationPanel panel = transportTypePanelControl.getConfigurationPanel(id); + if (panel instanceof IDataExchangeNode) { + if (panel instanceof IDataExchangeNode3) { + ((IDataExchangeNode3) panel).removeData(attributes); + } + } + } + IWizardConfigurationPanel panel = transportTypePanelControl.getActiveConfigurationPanel(); + if (panel instanceof IDataExchangeNode) { + ((IDataExchangeNode) panel).extractData(attributes); + } + } + + if (transportTypeControl != null) { + attributes.setProperty(IPeer.ATTR_TRANSPORT_NAME, transportTypeControl + .getSelectedTransportType()); + } + } + + /** + * Updates the control enablement. + */ + protected void updateEnablement() { + // Determine the input + final Object input = od; // getManagedForm().getInput(); + + // Determine if the peer is a static peer + final AtomicBoolean isStatic = new AtomicBoolean(); + final AtomicBoolean isRemote = new AtomicBoolean(); + Runnable runnable = new Runnable() { + @Override + public void run() { + if (input instanceof IPeerModel) { + isStatic.set(((IPeerModel) input).isStatic()); + isRemote.set(((IPeerModel) input).isRemote()); + } + } + }; + + if (Protocol.isDispatchThread()) runnable.run(); + else Protocol.invokeAndWait(runnable); + + // The transport type control is enabled for static peers + if (transportTypeControl != null) { + boolean enabled = !isReadOnly() && (input == null || (isStatic.get() && !isRemote.get())); + SWTControlUtil.setEnabled(transportTypeControl.getEditFieldControl(), enabled); + if (transportTypePanelControl != null) { + IWizardConfigurationPanel panel = transportTypePanelControl + .getConfigurationPanel(transportTypeControl + .getSelectedTransportType()); + if (panel != null) { + panel.setEnabled(enabled); + } + } + } + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.ui.forms.parts.AbstractSection#saveWidgetValues(org.eclipse.jface.dialogs.IDialogSettings) + */ + @Override + public void saveWidgetValues(IDialogSettings settings) { + super.saveWidgetValues(settings); + + if (settings != null) { + if (transportTypePanelControl != null) { + transportTypePanelControl.saveWidgetValues(settings, TransportSection.class.getSimpleName()); + } + } + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.ui.forms.parts.AbstractSection#restoreWidgetValues(org.eclipse.jface.dialogs.IDialogSettings) + */ + @Override + public void restoreWidgetValues(IDialogSettings settings) { + super.restoreWidgetValues(settings); + + if (settings != null) { + if (transportTypePanelControl != null) { + transportTypePanelControl.restoreWidgetValues(settings, TransportSection.class.getSimpleName()); + } + } + } +} -- cgit v1.2.3