/******************************************************************************* * Copyright (c) 2011, 2014 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.dialogs; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.jface.viewers.DecoratingStyledCellLabelProvider; import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider; import org.eclipse.jface.viewers.IBaseLabelProvider; import org.eclipse.jface.viewers.IContentProvider; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.StyledString; import org.eclipse.jface.viewers.TreePath; import org.eclipse.jface.viewers.TreeSelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Shell; import org.eclipse.tcf.core.TransientPeer; import org.eclipse.tcf.protocol.IPeer; import org.eclipse.tcf.protocol.Protocol; import org.eclipse.tcf.te.runtime.callback.AsyncCallbackCollector; import org.eclipse.tcf.te.runtime.callback.Callback; import org.eclipse.tcf.te.runtime.interfaces.callback.ICallback; import org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer; import org.eclipse.tcf.te.runtime.model.interfaces.IContainerModelNode; import org.eclipse.tcf.te.runtime.model.interfaces.contexts.IAsyncRefreshableCtx; import org.eclipse.tcf.te.runtime.model.interfaces.contexts.IAsyncRefreshableCtx.QueryState; import org.eclipse.tcf.te.runtime.model.interfaces.contexts.IAsyncRefreshableCtx.QueryType; import org.eclipse.tcf.te.runtime.persistence.interfaces.IURIPersistenceService; import org.eclipse.tcf.te.runtime.properties.PropertiesContainer; import org.eclipse.tcf.te.runtime.services.ServiceManager; import org.eclipse.tcf.te.tcf.core.interfaces.IPeerProperties; import org.eclipse.tcf.te.tcf.core.interfaces.ITransportTypes; import org.eclipse.tcf.te.tcf.core.util.persistence.PeerDataHelper; import org.eclipse.tcf.te.tcf.locator.interfaces.ILocatorModelListener; import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.ILocatorModel; import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.ILocatorNode; import org.eclipse.tcf.te.tcf.locator.interfaces.services.ILocatorModelLookupService; import org.eclipse.tcf.te.tcf.locator.interfaces.services.ILocatorModelRefreshService; import org.eclipse.tcf.te.tcf.locator.interfaces.services.ILocatorModelUpdateService; import org.eclipse.tcf.te.tcf.locator.model.ModelLocationUtil; import org.eclipse.tcf.te.tcf.locator.model.ModelManager; import org.eclipse.tcf.te.tcf.ui.editor.sections.TcpTransportSection; import org.eclipse.tcf.te.tcf.ui.help.IContextHelpIds; import org.eclipse.tcf.te.tcf.ui.navigator.ContentProvider; import org.eclipse.tcf.te.tcf.ui.nls.Messages; import org.eclipse.tcf.te.ui.async.UICallbackInvocationDelegate; import org.eclipse.tcf.te.ui.dialogs.AbstractSectionDialog; import org.eclipse.tcf.te.ui.forms.parts.AbstractSection; import org.eclipse.tcf.te.ui.views.extensions.CategoriesExtensionPointManager; import org.eclipse.tcf.te.ui.views.interfaces.ICategory; import org.eclipse.tcf.te.ui.views.interfaces.IUIConstants; import org.eclipse.tcf.te.ui.views.navigator.DelegatingLabelProvider; import org.eclipse.ui.forms.IManagedForm; /** * Locator node selection dialog implementation. */ public class LocatorNodeSelectionDialog extends AbstractTreeSelectionDialog implements ILocatorModelListener { Button addButton; Button deleteButton; Button refreshButton; final boolean isProxyAllowed; /** * Constructor. * * @param shell The shell used to view the dialog, or <code>null</code>. */ public LocatorNodeSelectionDialog(Shell shell, boolean isProxyAllowed) { super(shell, IContextHelpIds.LOCATOR_NODE_SELECTION_DIALOG); this.isProxyAllowed = isProxyAllowed; ModelManager.getLocatorModel().addListener(this); } /* (non-Javadoc) * @see org.eclipse.tcf.te.tcf.ui.dialogs.AbstractTreeSelectionDialog#createButtonAreaContent(org.eclipse.swt.widgets.Composite) */ @Override protected void createButtonAreaContent(Composite parent) { Composite comp = new Composite(parent, SWT.NONE); GridLayout gl = new GridLayout(); gl.marginWidth = 0; gl.marginHeight = 0; comp.setLayout(gl); GridData layoutData = new GridData(SWT.NONE, SWT.FILL, false, true); comp.setLayoutData(layoutData); addButton = new Button(comp, SWT.PUSH); layoutData = new GridData(SWT.FILL, SWT.FILL, false, false); addButton.setLayoutData(layoutData); addButton.setText(" " + Messages.LocatorNodeSelectionDialog_button_add + " "); //$NON-NLS-1$ //$NON-NLS-2$ addButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { onButtonAddSelected(); } }); deleteButton = new Button(comp, SWT.PUSH); layoutData = new GridData(SWT.FILL, SWT.FILL, false, false); deleteButton.setLayoutData(layoutData); deleteButton.setText(" " + Messages.LocatorNodeSelectionDialog_button_delete + " "); //$NON-NLS-1$ //$NON-NLS-2$ deleteButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { onButtonDeleteSelected(); } }); Composite spacer = new Composite(comp, SWT.NONE); layoutData = new GridData(SWT.FILL, SWT.FILL, false, true); spacer.setLayoutData(layoutData); refreshButton = new Button(comp, SWT.PUSH); layoutData = new GridData(SWT.FILL, SWT.FILL, false, false); refreshButton.setLayoutData(layoutData); refreshButton.setText(" " + Messages.LocatorNodeSelectionDialog_button_refresh + " "); //$NON-NLS-1$ //$NON-NLS-2$ refreshButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { onButtonRefreshSelected(); } }); } protected void onButtonAddSelected() { final ISelection sel = getViewer().getSelection(); if (sel instanceof IStructuredSelection) { Object element = ((IStructuredSelection) sel).getFirstElement(); String encProxies; if (element instanceof ICategory) { encProxies = null; } else if (element instanceof ILocatorNode) { ILocatorNode parent = (ILocatorNode) element; String parentProxies = parent.getPeer().getAttributes() .get(IPeerProperties.PROP_PROXIES); IPeer[] proxies = PeerDataHelper.decodePeerList(parentProxies); List<IPeer> proxiesList = new ArrayList<IPeer>(Arrays.asList(proxies)); proxiesList.add(parent.getPeer()); proxies = proxiesList.toArray(new IPeer[proxiesList.size()]); encProxies = PeerDataHelper.encodePeerList(proxies); } else { return; } AbstractSectionDialog dialog = new AbstractSectionDialog(getShell(), Messages.LocatorNodeSelectionDialog_add_dialogTitle, Messages.LocatorNodeSelectionDialog_add_title, Messages.LocatorNodeSelectionDialog_add_message, false, null) { @Override protected AbstractSection[] createSections(IManagedForm form, Composite parent) { return new AbstractSection[] { new TcpTransportSection(form, parent, false) }; } }; IPropertiesContainer data = new PropertiesContainer(); data.setProperty(IPeerProperties.PROP_PROXIES, encProxies); data.setProperty(IPeer.ATTR_TRANSPORT_NAME, ITransportTypes.TRANSPORT_TYPE_TCP); data.setProperty(IPeer.ATTR_IP_PORT, "1534"); //$NON-NLS-1$ dialog.setupData(data); if (dialog.open() == Window.OK) { dialog.extractData(data); String proxy = data.getStringProperty(IPeerProperties.PROP_PROXIES); String host = data.getStringProperty(IPeer.ATTR_IP_HOST); String port = data.getStringProperty(IPeer.ATTR_IP_PORT); String transport = data.getStringProperty(IPeer.ATTR_TRANSPORT_NAME); String id = transport + ":" + host + ":" + port; //$NON-NLS-1$ //$NON-NLS-2$ Map<String,String> attrs = new HashMap<String, String>(); attrs.put(IPeer.ATTR_ID, id); attrs.put(IPeer.ATTR_IP_HOST, host); attrs.put(IPeer.ATTR_IP_PORT, port); attrs.put(IPeer.ATTR_TRANSPORT_NAME, transport); attrs.put(IPeerProperties.PROP_PROXIES, proxy); final IPeer peer = new TransientPeer(attrs); Protocol.invokeLater(new Runnable() { @Override public void run() { final ILocatorModelLookupService lkup = ModelManager.getLocatorModel().getService(ILocatorModelLookupService.class); ILocatorModelRefreshService refresh = ModelManager.getLocatorModel().getService(ILocatorModelRefreshService.class); ILocatorNode node = lkup.lkupLocatorNode(peer); if (node == null || !node.isStatic()) { try { IURIPersistenceService persistenceService = ServiceManager.getInstance().getService(IURIPersistenceService.class); String id = peer.getID(); String name = id.replaceAll("\\W", "_").trim(); //$NON-NLS-1$ //$NON-NLS-2$ IPath basePath = ModelLocationUtil.getStaticLocatorsRootLocation(); IPath path = basePath.append(name).addFileExtension("locator"); //$NON-NLS-1$ int i = 0; while (path.toFile().exists()) { path = basePath.append(name+"_"+i).addFileExtension("locator"); //$NON-NLS-1$ //$NON-NLS-2$ } persistenceService.write(peer, path.toFile().toURI()); } catch (Exception e) { } refresh.refresh(new Callback() { @Override protected void internalDone(Object caller, org.eclipse.core.runtime.IStatus status) { final ILocatorNode node = lkup.lkupLocatorNode(peer); getShell().getDisplay().asyncExec(new Runnable() { @Override public void run() { if (node != null) { setSelection(new StructuredSelection(node)); updateSelection(getSelection()); } } }); } }); } else { refresh.refresh(node, new Callback() { @Override protected void internalDone(Object caller, org.eclipse.core.runtime.IStatus status) { final ILocatorNode node = lkup.lkupLocatorNode(peer); getShell().getDisplay().asyncExec(new Runnable() { @Override public void run() { if (node != null) { setSelection(new StructuredSelection(node)); updateSelection(getSelection()); } } }); } }); } } }); } } } protected void onButtonDeleteSelected() { final ISelection sel = getViewer().getSelection(); if (sel instanceof IStructuredSelection) { Protocol.invokeLater(new Runnable() { @Override public void run() { Object element = ((IStructuredSelection)sel).getFirstElement(); if (element instanceof ILocatorNode) { doDelete((ILocatorNode)element); ILocatorModelRefreshService refresh = ModelManager.getLocatorModel().getService(ILocatorModelRefreshService.class); refresh.refresh(null); } } }); } } protected void doDelete(ILocatorNode locatorNode) { for (ILocatorNode child : locatorNode.getChildren(ILocatorNode.class)) { doDelete(child); } if (locatorNode.isStatic()) { IURIPersistenceService persistenceService = ServiceManager.getInstance() .getService(IURIPersistenceService.class); try { persistenceService.delete(locatorNode.isDiscovered() ? locatorNode .getProperty(ILocatorNode.PROPERTY_STATIC_INSTANCE) : locatorNode .getPeer(), null); } catch (Exception e) { } ILocatorModelUpdateService update = ModelManager.getLocatorModel() .getService(ILocatorModelUpdateService.class); update.remove(locatorNode.getPeer()); } } protected void onButtonRefreshSelected() { final ISelection sel = getViewer().getSelection(); if (sel instanceof IStructuredSelection) { Protocol.invokeLater(new Runnable() { @Override public void run() { ILocatorModelRefreshService service = ModelManager.getLocatorModel().getService(ILocatorModelRefreshService.class); Object element = ((IStructuredSelection)sel).getFirstElement(); if (element instanceof ICategory) { service.refresh(null); } if (element instanceof ILocatorNode) { service.refresh((ILocatorNode)element, null); } } }); } } /* (non-Javadoc) * @see org.eclipse.tcf.te.ui.jface.dialogs.CustomTitleAreaDialog#dispose() */ @Override protected void dispose() { super.dispose(); ModelManager.getLocatorModel().removeListener(this); } /* (non-Javadoc) * @see org.eclipse.tcf.te.tcf.ui.dialogs.AbstractTreeSelectionDialog#getInput() */ @Override protected Object getInput() { return ModelManager.getLocatorModel(); } /** * A styled label provider for the target selection list. */ static class TargetStyledLabelProvider extends DelegatingLabelProvider implements IStyledLabelProvider { @Override public StyledString getStyledText(Object element) { return new StyledString(getText(element)); } } /* (non-Javadoc) * @see org.eclipse.tcf.te.tcf.ui.dialogs.AbstractTreeSelectionDialog#getLabelProvider() */ @Override protected IBaseLabelProvider getLabelProvider() { TargetStyledLabelProvider labelProvider = new TargetStyledLabelProvider(); return new DecoratingStyledCellLabelProvider(labelProvider, labelProvider, null); } /* (non-Javadoc) * @see org.eclipse.tcf.te.tcf.ui.dialogs.AbstractTreeSelectionDialog#getContentProvider() */ @Override protected IContentProvider getContentProvider() { return new ContentProvider() { @Override public Object[] getChildren(Object parentElement) { if (isProxyAllowed || parentElement instanceof ILocatorModel || parentElement instanceof ICategory) { return super.getChildren(parentElement); } return new Object[0]; } @Override public boolean hasChildren(Object element) { if (isProxyAllowed || element instanceof ILocatorModel || element instanceof ICategory) { return super.hasChildren(element); } return false; } }; } protected Object getViewerSelection() { ISelection sel = getViewer().getSelection(); if (sel instanceof IStructuredSelection) { return ((IStructuredSelection)sel).getFirstElement(); } return null; } /* (non-Javadoc) * @see org.eclipse.tcf.te.tcf.ui.dialogs.AbstractTreeSelectionDialog#isValidSelection() */ @Override protected boolean isValidSelection() { Object element = getViewerSelection(); return element instanceof ICategory || element instanceof ILocatorNode; } /* (non-Javadoc) * @see org.eclipse.tcf.te.tcf.ui.dialogs.AbstractTreeSelectionDialog#getDialogTitle() */ @Override protected String getDialogTitle() { return Messages.LocatorNodeSelectionDialog_dialogTitle; } /* (non-Javadoc) * @see org.eclipse.tcf.te.tcf.ui.dialogs.AbstractTreeSelectionDialog#getTitle() */ @Override protected String getTitle() { return Messages.LocatorNodeSelectionDialog_title; } /* (non-Javadoc) * @see org.eclipse.tcf.te.tcf.ui.dialogs.AbstractTreeSelectionDialog#getDefaultMessage() */ @Override protected String getDefaultMessage() { return Messages.LocatorNodeSelectionDialog_message; } /* (non-Javadoc) * @see org.eclipse.tcf.te.tcf.locator.interfaces.ILocatorModelListener#modelChanged(org.eclipse.tcf.te.tcf.locator.interfaces.nodes.ILocatorModel, org.eclipse.tcf.te.tcf.locator.interfaces.nodes.ILocatorNode, boolean) */ @Override public void modelChanged(ILocatorModel model, ILocatorNode locatorNode, boolean added) { refresh(); } /* (non-Javadoc) * @see org.eclipse.tcf.te.tcf.locator.interfaces.ILocatorModelListener#modelDisposed(org.eclipse.tcf.te.tcf.locator.interfaces.nodes.ILocatorModel) */ @Override public void modelDisposed(ILocatorModel model) { } /* (non-Javadoc) * @see org.eclipse.tcf.te.tcf.ui.dialogs.AbstractTreeSelectionDialog#updateEnablement(org.eclipse.jface.viewers.TreeViewer) */ @Override protected void updateEnablement(TreeViewer viewer) { boolean valid = isValidSelection(); if (addButton != null && !addButton.isDisposed()) { if (isProxyAllowed) { addButton.setEnabled(valid); } else { addButton.setEnabled(getViewerSelection() instanceof ICategory); } } if (refreshButton != null && !refreshButton.isDisposed()) { refreshButton.setEnabled(valid); } if (deleteButton != null && !deleteButton.isDisposed()) { valid = false; ISelection sel = getViewer().getSelection(); if (sel instanceof IStructuredSelection) { Object element = ((IStructuredSelection)sel).getFirstElement(); if (element instanceof ILocatorNode) { valid = ((ILocatorNode)element).isStatic(); } } deleteButton.setEnabled(valid); } super.updateEnablement(viewer); } /* (non-Javadoc) * @see org.eclipse.tcf.te.tcf.ui.dialogs.AbstractTreeSelectionDialog#updateSelection(org.eclipse.jface.viewers.ISelection) */ @Override protected void updateSelection(ISelection selection) { ICategory category = CategoriesExtensionPointManager.getInstance().getCategory(IUIConstants.ID_CAT_NEIGHBORHOOD, false); if (selection instanceof IStructuredSelection) { final Object element = ((IStructuredSelection)selection).getFirstElement(); if (element instanceof ILocatorNode) { final List<Object> treePath = new ArrayList<Object>(); treePath.add(category); treePath.add(element); Protocol.invokeAndWait(new Runnable() { @Override public void run() { IContainerModelNode container = ((ILocatorNode)element).getParent(); while (container != null) { treePath.add(1, container); container = container.getParent(); } } }); final TreePath path = new TreePath(treePath.toArray()); final AsyncCallbackCollector collector = new AsyncCallbackCollector(new Callback() { @Override protected void internalDone(Object caller, IStatus status) { if (viewer != null && !viewer.getTree().isDisposed()) { viewer.refresh(); viewer.setSelection(new TreeSelection(path), true); } } }, new UICallbackInvocationDelegate()); for (Object pathNode : treePath) { if (pathNode instanceof ILocatorNode) { final ILocatorNode locatorNode = (ILocatorNode)pathNode; IAsyncRefreshableCtx refreshCtx = (IAsyncRefreshableCtx)locatorNode.getAdapter(IAsyncRefreshableCtx.class); if (refreshCtx.getQueryState(QueryType.CONTEXT) != QueryState.DONE || refreshCtx.getQueryState(QueryType.CHILD_LIST) != QueryState.DONE) { final ICallback cb = locatorNode.isStatic() ? null : new AsyncCallbackCollector.SimpleCollectorCallback(collector); Protocol.invokeLater(new Runnable() { @Override public void run() { ModelManager.getLocatorModel().getService(ILocatorModelRefreshService.class).refresh(locatorNode, cb); } }); } } } collector.initDone(); } } else { viewer.expandToLevel(2); viewer.setSelection(new StructuredSelection(category)); } } }