diff options
Diffstat (limited to 'plugins')
24 files changed, 2361 insertions, 1381 deletions
diff --git a/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/launch/TCFCDTLaunchDelegate.java b/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/launch/TCFCDTLaunchDelegate.java index f15b68f35..4c254cf5b 100644 --- a/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/launch/TCFCDTLaunchDelegate.java +++ b/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/launch/TCFCDTLaunchDelegate.java @@ -22,6 +22,7 @@ import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.debug.core.IStatusHandler; import org.eclipse.tcf.internal.debug.launch.TCFLaunchDelegate; import org.eclipse.tcf.internal.debug.model.TCFLaunch; +import org.eclipse.tcf.internal.debug.ui.launch.ContextSelection; import org.eclipse.tcf.util.TCFTask; /** @@ -90,7 +91,7 @@ public class TCFCDTLaunchDelegate extends TCFLaunchDelegate { if (prompter != null) { Object result = prompter.handleStatus(contextPrompt, config); if (result instanceof ContextSelection) { - return (ContextSelection) result; + return (ContextSelection)result; } } return null; diff --git a/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/disassembly/TCFDisassemblyBackend.java b/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/disassembly/TCFDisassemblyBackend.java index 51068758a..37df306f7 100644 --- a/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/disassembly/TCFDisassemblyBackend.java +++ b/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/disassembly/TCFDisassemblyBackend.java @@ -266,7 +266,7 @@ public class TCFDisassemblyBackend extends AbstractDisassemblyBackend { done = true; /* Don't call setUpdatePending() if pending state was reset by the view */ if (context_cnt != fContextCount) return; - assert fCallback.getUpdatePending(); + if (!fCallback.getUpdatePending()) return; fCallback.setUpdatePending(false); } } diff --git a/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/launch/ProcessListControl.java b/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/launch/ProcessListControl.java deleted file mode 100644 index 616329d6c..000000000 --- a/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/launch/ProcessListControl.java +++ /dev/null @@ -1,505 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 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.internal.cdt.ui.launch; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; - -import org.eclipse.debug.ui.DebugUITools; -import org.eclipse.debug.ui.IDebugUIConstants; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.DisposeEvent; -import org.eclipse.swt.events.DisposeListener; -import org.eclipse.swt.graphics.Font; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Listener; -import org.eclipse.swt.widgets.Tree; -import org.eclipse.swt.widgets.TreeItem; -import org.eclipse.tcf.protocol.IChannel; -import org.eclipse.tcf.protocol.IChannel.IChannelListener; -import org.eclipse.tcf.protocol.IPeer; -import org.eclipse.tcf.protocol.IToken; -import org.eclipse.tcf.protocol.Protocol; -import org.eclipse.tcf.services.IProcesses; -import org.eclipse.tcf.services.IProcesses.ProcessContext; - -public class ProcessListControl { - - private final class ProcessListener implements IProcesses.ProcessesListener { - public void exited(final String process_id, int exit_code) { - if (display != null) { - display.asyncExec(new Runnable() { - public void run() { - ProcessInfo info = findProcessInfo(root_info, process_id); - if (info != null && info.parent != null && info.parent.children != null) { - info.parent.children = null; - loadChildren(info.parent); - } - } - }); - } - } - } - - static class ProcessInfo { - String name; - String id; - boolean isContainer; - ProcessInfo[] children; - Throwable children_error; - int index; - boolean children_pending; - ProcessInfo parent; - protected boolean isAttached; - } - - private Tree fProcessTree; - private Display display; - private IPeer fPeer; - private final ProcessInfo root_info = new ProcessInfo(); - private IChannel fChannel; - private IProcesses fProcesses; - protected final ProcessListener fProcessListener = new ProcessListener(); - private String fContextToSelect; - private LinkedList<String> fPathToSelect; - private Composite fComposite; - - public ProcessListControl(Composite parent) { - display = parent.getDisplay(); - parent.addDisposeListener(new DisposeListener() { - public void widgetDisposed(DisposeEvent e) { - handleDispose(); - } - }); - createProcessListArea(parent); - } - - public void setInput(IPeer peer) { - if (peer == fPeer) { - return; - } - if (fPeer != null) { - Protocol.invokeAndWait(new Runnable() { - public void run() { - disconnectPeer(); - } - }); - } - fProcessTree.setItemCount(0); - root_info.children = null; - fPeer = peer; - if (fPeer != null) { - Protocol.invokeAndWait(new Runnable() { - public void run() { - connectPeer(); - } - }); - } - } - - public Control getControl() { - return fComposite; - } - - public Tree getTree() { - return fProcessTree; - } - - public ProcessInfo getSelection() { - if (fProcessTree != null) { - TreeItem[] items = fProcessTree.getSelection(); - if (items.length > 0) { - ProcessInfo info = findProcessInfo(items[0]); - return info; - } - } - return null; - } - - private void createProcessListArea(Composite parent) { - Font font = parent.getFont(); - Composite composite = new Composite(parent, SWT.NONE); - composite.setFont(font); - GridLayout layout = new GridLayout(1, false); - layout.marginWidth = 0; - layout.marginHeight = 0; - composite.setLayout(layout); - composite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true)); - fComposite = composite; - - fProcessTree = new Tree(composite, SWT.VIRTUAL | SWT.BORDER | SWT.SINGLE); - GridData gd = new GridData(GridData.FILL_BOTH); - gd.minimumHeight = 150; - gd.minimumWidth = 470; - fProcessTree.setLayoutData(gd); - fProcessTree.setFont(font); - fProcessTree.addListener(SWT.SetData, new Listener() { - public void handleEvent(Event event) { - TreeItem item = (TreeItem)event.item; - ProcessInfo info = findProcessInfo(item); - if (info == null) { - updateItems(item.getParentItem(), false); - } - else { - fillItem(item, info); - } - } - }); - } - - private void handleDispose() { - Protocol.invokeAndWait(new Runnable() { - public void run() { - disconnectPeer(); - if (fProcesses != null) { - fProcesses.removeListener(fProcessListener); - fProcesses = null; - } - display = null; - } - }); - } - - protected void disconnectPeer() { - if (fChannel != null && fChannel.getState() != IChannel.STATE_CLOSED) { - fChannel.close(); - } - } - - protected void connectPeer() { - final IChannel channel = fPeer.openChannel(); - fChannel = channel; - fProcesses = null; - channel.addChannelListener(new IChannelListener() { - public void congestionLevel(int level) { - } - public void onChannelClosed(final Throwable error) { - if (fChannel != channel) return; - fChannel = null; - if (display != null) { - display.asyncExec(new Runnable() { - public void run() { - if (root_info.children_pending) return; - root_info.children = null; - root_info.children_error = error; - updateItems(root_info); - } - }); - } - } - public void onChannelOpened() { - if (fChannel != channel) return; - fProcesses = fChannel.getRemoteService(IProcesses.class); - if (fProcesses != null) { - fProcesses.addListener(fProcessListener); - if (fContextToSelect != null) { - final LinkedList<String> contextPath = new LinkedList<String>(); - contextPath.addFirst(fContextToSelect); - fProcesses.getContext(fContextToSelect, new IProcesses.DoneGetContext() { - public void doneGetContext(IToken token, Exception error, ProcessContext context) { - if (error == null) { - String parentId = context.getParentID(); - if (parentId != null) { - contextPath.addFirst(parentId); - fProcesses.getContext(parentId, this); - return; - } - if (display != null) { - display.asyncExec(new Runnable() { - public void run() { - fPathToSelect = contextPath; - expandSelect(); - } - }); - } - } - } - }); - } - } - if (display != null) { - display.asyncExec(new Runnable() { - public void run() { - if (root_info.children_pending) return; - root_info.children = null; - root_info.children_error = null; - updateItems(root_info); - } - }); - } - } - }); - } - - private void updateItems(TreeItem parent_item, boolean reload) { - final ProcessInfo parent_info = findProcessInfo(parent_item); - if (parent_info == null) { - parent_item.setText("Invalid"); - } - else { - if (reload && parent_info.children_error != null) { - loadChildren(parent_info); - } - display.asyncExec(new Runnable() { - public void run() { - updateItems(parent_info); - } - }); - } - } - - private void updateItems(final ProcessInfo parent) { - if (display == null) return; - assert Thread.currentThread() == display.getThread(); - TreeItem[] items = null; - boolean expanded = true; - if (parent.children == null || parent.children_error != null) { - if (parent == root_info) { - fProcessTree.setItemCount(1); - items = fProcessTree.getItems(); - } - else { - TreeItem item = findItem(parent); - if (item == null) return; - expanded = item.getExpanded(); - item.setItemCount(1); - items = item.getItems(); - } - assert items.length == 1; - items[0].removeAll(); - if (parent.children_pending) { - items[0].setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND)); - items[0].setText("Pending..."); - } - else if (parent.children_error != null) { - String msg = parent.children_error.getMessage(); - if (msg == null) msg = parent.children_error.getClass().getName(); - else msg = msg.replace('\n', ' '); - items[0].setForeground(display.getSystemColor(SWT.COLOR_RED)); - items[0].setText(msg); - items[0].setImage((Image) null); - } - else if (expanded) { - loadChildren(parent); - items[0].setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND)); - items[0].setText("Pending..."); - } - else { - items[0].setText(""); - } - } - else { - ProcessInfo[] arr = parent.children; - if (parent == root_info) { - fProcessTree.setItemCount(arr.length); - items = fProcessTree.getItems(); - } - else { - TreeItem item = findItem(parent); - if (item == null) return; - expanded = item.getExpanded(); - item.setItemCount(expanded ? arr.length : 1); - items = item.getItems(); - } - if (expanded) { - assert items.length == arr.length; - for (int i = 0; i < items.length; i++) fillItem(items[i], arr[i]); - // auto-expand single children - if (items.length == 1 && !items[0].getExpanded()) { - items[0].setExpanded(true); - } - expandSelect(); - } - else { - items[0].setText(""); - } - } - } - - private void expandSelect() { - if (fPathToSelect == null) return; - if (fPathToSelect.isEmpty()) { - fPathToSelect = null; - fContextToSelect = null; - return; - } - do { - String id = fPathToSelect.get(0); - ProcessInfo info = findProcessInfo(root_info, id); - if (info == null) break; - TreeItem item = findItem(info); - if (item == null) break; - fPathToSelect.removeFirst(); - if (fPathToSelect.isEmpty()) { - fProcessTree.setSelection(item); - } else { - item.setExpanded(true); - } - } while (!fPathToSelect.isEmpty()); - } - - private void loadChildren(final ProcessInfo parent) { - assert Thread.currentThread() == display.getThread(); - if (parent.children_pending) return; - assert parent.children == null; - parent.children_pending = true; - parent.children_error = null; - Protocol.invokeLater(new Runnable() { - public void run() { - final IProcesses proc = fProcesses; - if (proc == null || !canHaveChildren(parent)) { - doneLoadChildren(parent, null, new ProcessInfo[0]); - } - else { - proc.getChildren(parent.id, false, new IProcesses.DoneGetChildren() { - public void doneGetChildren(IToken token, Exception error, String[] context_ids) { - if (error != null) { - doneLoadChildren(parent, error, null); - } else if (context_ids.length > 0){ - final List<ProcessInfo> contextInfos = new ArrayList<ProcessInfo>(context_ids.length); - final Set<IToken> pending = new HashSet<IToken>(); - for (String id : context_ids) { - pending.add(proc.getContext(id, new IProcesses.DoneGetContext() { - public void doneGetContext(IToken token, Exception error, ProcessContext context) { - if (context != null) { - ProcessInfo info = new ProcessInfo(); - info.parent = parent; - info.id = context.getID(); - info.name = context.getName(); - if (info.name == null || info.name.length() == 0) { - info.name = info.id; - } else { - info.name += " [" + info.id + ']'; - } - info.isContainer = false; - info.isAttached = context.isAttached(); - info.index = contextInfos.size(); - contextInfos.add(info); - } - pending.remove(token); - if (pending.isEmpty()) { - doneLoadChildren(parent, null, contextInfos.toArray(new ProcessInfo[contextInfos.size()])); - } - } - })); - } - } else { - doneLoadChildren(parent, null, new ProcessInfo[0]); - } - } - }); - } - } - }); - } - - private void doneLoadChildren(final ProcessInfo parent, final Throwable error, final ProcessInfo[] children) { - assert Protocol.isDispatchThread(); - assert error == null || children == null; - if (display == null) return; - display.asyncExec(new Runnable() { - public void run() { - assert parent.children_pending; - assert parent.children == null; - parent.children_pending = false; - parent.children = children; - parent.children_error = error; - updateItems(parent); - } - }); - } - - public ProcessInfo findProcessInfo(TreeItem item) { - assert Thread.currentThread() == display.getThread(); - if (item == null) return root_info ; - TreeItem parent = item.getParentItem(); - ProcessInfo info = findProcessInfo(parent); - if (info == null) return null; - if (info.children == null) return null; - if (info.children_error != null) return null; - int i = parent == null ? fProcessTree.indexOf(item) : parent.indexOf(item); - if (i < 0 || i >= info.children.length) return null; - assert info.children[i].index == i; - return info.children[i]; - } - - public ProcessInfo findProcessInfo(ProcessInfo parent, String id) { - assert Thread.currentThread() == display.getThread(); - if (id == null) return root_info; - if (id.equals(parent.id)) return parent; - ProcessInfo[] childInfos = parent.children; - if (childInfos != null) { - for (ProcessInfo contextInfo : childInfos) { - ProcessInfo found = findProcessInfo(contextInfo, id); - if (found != null) { - return found; - } - } - } - return null; - } - - private TreeItem findItem(ProcessInfo info) { - if (info == null) return null; - assert info.parent != null; - if (info.parent == root_info) { - int n = fProcessTree.getItemCount(); - if (info.index >= n) return null; - return fProcessTree.getItem(info.index); - } - TreeItem i = findItem(info.parent); - if (i == null) return null; - int n = i.getItemCount(); - if (info.index >= n) return null; - return i.getItem(info.index); - } - - private void fillItem(TreeItem item, ProcessInfo info) { - assert Thread.currentThread() == display.getThread(); - Object data = item.getData("TCFContextInfo"); - if (data != null && data != info) item.removeAll(); - item.setData("TCFContextInfo", info); - String text = info.name != null ? info.name : info.id; - item.setText(text); - item.setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND)); - item.setImage(getImage(info)); - if (!canHaveChildren(info)) item.setItemCount(0); - else if (info.children == null || info.children_error != null) item.setItemCount(1); - else item.setItemCount(info.children.length); - } - - private boolean canHaveChildren(ProcessInfo info) { - return info.isContainer || info == root_info; - } - - private Image getImage(ProcessInfo info) { - return DebugUITools.getImage(IDebugUIConstants.IMG_OBJS_OS_PROCESS); - } - - public void selectContext(final String contextId) { - fPathToSelect = null; - Protocol.invokeLater(new Runnable() { - public void run() { - fContextToSelect = contextId; - } - }); - } - -} diff --git a/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/launch/ProcessPrompter.java b/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/launch/ProcessPrompter.java index 4a0fa0294..a87c88c8a 100644 --- a/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/launch/ProcessPrompter.java +++ b/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/launch/ProcessPrompter.java @@ -15,19 +15,22 @@ import org.eclipse.core.runtime.IStatus; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.IStatusHandler; import org.eclipse.jface.window.Window; -import org.eclipse.tcf.internal.cdt.launch.ContextSelection; import org.eclipse.tcf.internal.debug.launch.TCFLaunchDelegate; +import org.eclipse.tcf.internal.debug.ui.launch.ContextSelection; +import org.eclipse.tcf.internal.debug.ui.launch.ContextSelectionDialog; import org.eclipse.ui.PlatformUI; public class ProcessPrompter implements IStatusHandler { public Object handleStatus(IStatus status, Object source) throws CoreException { ILaunchConfiguration config = (ILaunchConfiguration) source; - String peerId = config.getAttribute(TCFLaunchDelegate.ATTR_PEER_ID, (String) null); - String contextId = config.getAttribute("attach_to_process", (String) null); - if (peerId == null || contextId == null) { - ContextSelection selection = new ContextSelection(peerId, contextId); - ProcessSelectionDialog diag = new ProcessSelectionDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow()); + String peerId = config.getAttribute(TCFLaunchDelegate.ATTR_PEER_ID, (String)null); + String contextPath = config.getAttribute(TCFLaunchDelegate.ATTR_ATTACH_PATH, (String)null); + if (peerId == null || contextPath == null) { + ContextSelection selection = new ContextSelection(); + selection.fPeerId = peerId; + selection.fContextFullName = contextPath; + ContextSelectionDialog diag = new ContextSelectionDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow(), true); diag.setSelection(selection); if (diag.open() == Window.OK) { return diag.getSelection(); @@ -35,5 +38,4 @@ public class ProcessPrompter implements IStatusHandler { } return null; } - } diff --git a/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/launch/RemoteCMainTab.java b/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/launch/RemoteCMainTab.java index 64f0cbda0..79ece2719 100644 --- a/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/launch/RemoteCMainTab.java +++ b/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/launch/RemoteCMainTab.java @@ -22,7 +22,6 @@ import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; -import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.window.IShellProvider; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; @@ -37,8 +36,10 @@ import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; -import org.eclipse.tcf.internal.cdt.ui.launch.PeerListControl.PeerInfo; import org.eclipse.tcf.internal.debug.launch.TCFLaunchDelegate; +import org.eclipse.tcf.internal.debug.ui.launch.PeerListControl; +import org.eclipse.tcf.internal.debug.ui.launch.PeerListControl.PeerInfo; +import org.eclipse.tcf.internal.debug.ui.launch.RemoteFileSelectionDialog; import org.eclipse.tcf.protocol.IChannel; import org.eclipse.tcf.protocol.IChannel.IChannelListener; import org.eclipse.tcf.services.IFileSystem; @@ -122,7 +123,8 @@ public class RemoteCMainTab extends CMainTab implements IShellProvider { if (fSelectedPeer == null) { setErrorMessage("No target selected."); valid = false; - } else if (!fPeerHasProcessesService) { + } + else if (!fPeerHasProcessesService) { setErrorMessage("Selected target does not support 'Processes' service"); valid = false; } @@ -242,15 +244,7 @@ public class RemoteCMainTab extends CMainTab implements IShellProvider { protected void updatePeerFromConfig(ILaunchConfiguration config) { try { String peerId = config.getAttribute(TCFLaunchDelegate.ATTR_PEER_ID, (String) null); - if (peerId != null) { - PeerInfo info = fPeerList.findPeerInfo(peerId); - if (info != null) { - fPeerList.setSelection(new StructuredSelection(info)); - handlePeerSelectionChanged(); - } else { - fPeerList.setInitialSelectedPeerId(peerId); - } - } + fPeerList.setInitialSelection(peerId); } catch (CoreException e) { // Ignore diff --git a/plugins/org.eclipse.tcf.debug.ui/icons/application_tab.gif b/plugins/org.eclipse.tcf.debug.ui/icons/application_tab.gif Binary files differnew file mode 100644 index 000000000..aa15e0a47 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/icons/application_tab.gif diff --git a/plugins/org.eclipse.tcf.debug.ui/icons/download_tab.gif b/plugins/org.eclipse.tcf.debug.ui/icons/download_tab.gif Binary files differnew file mode 100644 index 000000000..ad5e74dec --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/icons/download_tab.gif diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/ImageCache.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/ImageCache.java index c16467746..c195b5c61 100644 --- a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/ImageCache.java +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/ImageCache.java @@ -30,7 +30,9 @@ public class ImageCache { public static final String IMG_TCF = "icons/tcf.gif", IMG_TARGET_TAB = "icons/target_tab.gif", + IMG_DOWNLOAD_TAB = "icons/download_tab.gif", IMG_TARGET_WIZARD = "icons/full/wizban/debug_wiz.png", + IMG_APPLICATION_TAB = "icons/application_tab.gif", IMG_ARGUMENTS_TAB = "icons/arguments_tab.gif", IMG_ATTRIBUTE = "icons/attribute.gif", IMG_PATH = "icons/path.gif", diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/ContextListControl.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/ContextListControl.java new file mode 100644 index 000000000..ee93d532b --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/ContextListControl.java @@ -0,0 +1,653 @@ +/******************************************************************************* + * Copyright (c) 2011, 2013 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.internal.debug.ui.launch; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeItem; +import org.eclipse.tcf.internal.debug.ui.ImageCache; +import org.eclipse.tcf.internal.debug.ui.model.TCFModel; +import org.eclipse.tcf.protocol.IChannel; +import org.eclipse.tcf.protocol.IChannel.IChannelListener; +import org.eclipse.tcf.protocol.IPeer; +import org.eclipse.tcf.protocol.IToken; +import org.eclipse.tcf.protocol.Protocol; +import org.eclipse.tcf.services.IProcesses; +import org.eclipse.tcf.services.IProcesses.ProcessContext; +import org.eclipse.tcf.services.IRunControl; +import org.eclipse.tcf.services.IRunControl.RunControlContext; +import org.eclipse.tcf.services.ISysMonitor; +import org.eclipse.tcf.services.ISysMonitor.SysMonitorContext; +import org.eclipse.tcf.util.TCFTask; + +public class ContextListControl { + + private final class ProcessListener implements IProcesses.ProcessesListener { + public void exited(final String process_id, int exit_code) { + onContextRemoved(process_id); + } + } + + private final class ContextListener implements IRunControl.RunControlListener { + @Override + public void contextAdded(RunControlContext[] contexts) { + for (RunControlContext ctx : contexts) { + onContextAdded(ctx.getParentID()); + } + } + @Override + public void contextChanged(RunControlContext[] contexts) { + } + @Override + public void contextRemoved(String[] context_ids) { + for (String id : context_ids) { + onContextRemoved(id); + } + } + @Override + public void contextSuspended(String context, String pc, String reason, Map<String, Object> params) { + } + @Override + public void contextResumed(String context) { + } + @Override + public void containerSuspended(String context, String pc, String reason, Map<String, Object> params, String[] suspended_ids) { + } + @Override + public void containerResumed(String[] context_ids) { + } + @Override + public void contextException(String context, String msg) { + } + } + + static class ContextInfo { + String name; + String id; + boolean is_attached; + boolean is_container; + boolean has_state; + long pid; + String[] cmd_line; + ContextInfo[] children; + Throwable children_error; + boolean children_pending; + boolean children_reload; + ContextInfo parent; + } + + private Composite composite; + private Tree ctx_tree; + private Display display; + private IChannel channel; + private String channel_state; + private final ContextInfo root_info = new ContextInfo(); + private final ProcessListener prs_listener = new ProcessListener(); + private final ContextListener ctx_listener = new ContextListener(); + private final boolean processes; + private String initial_selection; + + public ContextListControl(Composite parent, boolean processes) { + this.processes = processes; + display = parent.getDisplay(); + parent.addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + Protocol.invokeAndWait(new Runnable() { + public void run() { + disconnectPeer(); + display = null; + } + }); + } + }); + createContextListArea(parent); + } + + public void setInput(final IPeer peer) { + assert Thread.currentThread() == display.getThread(); + channel = new TCFTask<IChannel>() { + public void run() { + disconnectPeer(); + done(connectPeer(peer)); + } + }.getE(); + root_info.children = null; + root_info.children_error = null; + root_info.children_pending = false; + root_info.children_reload = false; + loadChildren(root_info); + } + + public Control getControl() { + return composite; + } + + public Tree getTree() { + return ctx_tree; + } + + public ContextInfo getSelection() { + if (ctx_tree != null) { + initial_selection = null; + TreeItem[] items = ctx_tree.getSelection(); + if (items.length > 0) { + ContextInfo info = findInfo(items[0]); + return info; + } + } + return null; + } + + private void createContextListArea(Composite parent) { + Font font = parent.getFont(); + composite = new Composite(parent, SWT.NONE); + composite.setFont(font); + GridLayout layout = new GridLayout(1, false); + layout.marginWidth = 0; + layout.marginHeight = 0; + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true)); + + ctx_tree = new Tree(composite, SWT.VIRTUAL | SWT.BORDER | SWT.SINGLE); + GridData gd = new GridData(GridData.FILL_BOTH); + gd.minimumHeight = 150; + gd.minimumWidth = 470; + ctx_tree.setLayoutData(gd); + ctx_tree.setFont(font); + ctx_tree.addListener(SWT.SetData, new Listener() { + public void handleEvent(Event event) { + TreeItem item = (TreeItem)event.item; + ContextInfo info = findInfo(item); + if (info == null) { + updateItems(item.getParentItem(), false); + } + else { + fillItem(item, info); + } + } + }); + } + + protected void disconnectPeer() { + if (channel != null && channel.getState() != IChannel.STATE_CLOSED) { + channel.close(); + } + } + + protected IChannel connectPeer(IPeer peer) { + if (peer == null) return null; + final IChannel channel = peer.openChannel(); + channel.addChannelListener(new IChannelListener() { + public void congestionLevel(int level) { + } + public void onChannelClosed(final Throwable error) { + if (display != null) { + display.asyncExec(new Runnable() { + public void run() { + if (ContextListControl.this.channel != channel) return; + root_info.children_error = error; + loadChildren(root_info); + } + }); + } + } + public void onChannelOpened() { + if (processes) { + IProcesses service = channel.getRemoteService(IProcesses.class); + if (service != null) service.addListener(prs_listener); + } + else { + IRunControl service = channel.getRemoteService(IRunControl.class); + if (service != null) service.addListener(ctx_listener); + } + if (display != null) { + display.asyncExec(new Runnable() { + public void run() { + if (ContextListControl.this.channel != channel) return; + loadChildren(root_info); + updateItems(root_info); + } + }); + } + } + }); + return channel; + } + + private void updateItems(TreeItem parent_item, boolean reload) { + final ContextInfo parent_info = findInfo(parent_item); + if (parent_info == null) { + parent_item.setText("Invalid"); + } + else { + if (reload && parent_info.children_error != null) { + loadChildren(parent_info); + } + display.asyncExec(new Runnable() { + public void run() { + updateItems(parent_info); + } + }); + } + } + + private void updateItems(final ContextInfo parent) { + if (display == null) return; + assert Thread.currentThread() == display.getThread(); + TreeItem[] items = null; + boolean expanded = true; + if (parent.children == null || parent.children_error != null) { + if (parent == root_info) { + ctx_tree.deselectAll(); + ctx_tree.setItemCount(1); + items = ctx_tree.getItems(); + } + else { + TreeItem item = findItem(parent); + if (item == null) return; + expanded = item.getExpanded(); + item.setItemCount(1); + items = item.getItems(); + } + assert items.length == 1; + items[0].removeAll(); + items[0].setImage((Image)null); + items[0].setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND)); + if (parent.children_pending) { + items[0].setText("Pending..."); + } + else if (parent.children_error != null) { + String msg = TCFModel.getErrorMessage(parent.children_error, false); + items[0].setForeground(display.getSystemColor(SWT.COLOR_RED)); + items[0].setText(msg); + } + else if (channel_state != null) { + items[0].setText(channel_state); + } + else if (expanded) { + loadChildren(parent); + items[0].setText("Pending..."); + } + else { + items[0].setText(""); + } + } + else { + ContextInfo[] arr = parent.children; + if (parent == root_info) { + ctx_tree.setItemCount(arr.length); + items = ctx_tree.getItems(); + } + else { + TreeItem item = findItem(parent); + if (item == null) return; + expanded = item.getExpanded(); + item.setItemCount(expanded ? arr.length : 1); + items = item.getItems(); + } + if (expanded) { + assert items.length == arr.length; + for (int i = 0; i < items.length; i++) fillItem(items[i], arr[i]); + // auto-expand single children + if (items.length == 1 && !items[0].getExpanded()) { + items[0].setExpanded(true); + } + } + else { + items[0].setText(""); + } + } + if (initial_selection != null) { + setInitialSelection(initial_selection); + } + } + + private void loadChildren(final ContextInfo parent) { + assert Thread.currentThread() == display.getThread(); + final IChannel channel = this.channel; + parent.children_reload = true; + if (parent.children_pending) return; + parent.children_reload = false; + parent.children_pending = true; + Protocol.invokeLater(new Runnable() { + public void run() { + if (channel == null || channel.getState() != IChannel.STATE_OPEN) { + doneLoadChildren(channel, parent, null, new ContextInfo[0]); + } + else if (processes) { + loadProcessChildren(channel, parent); + } + else { + loadContextChildren(channel, parent); + } + } + }); + } + + private void loadProcessChildren(final IChannel channel, final ContextInfo parent) { + final IProcesses service = channel.getRemoteService(IProcesses.class); + final ISysMonitor sysmon = channel.getRemoteService(ISysMonitor.class); + if (service == null) { + doneLoadChildren(channel, parent, new Exception("Peer does not support Processes service"), null); + } + else if (!canHaveChildren(parent)) { + doneLoadChildren(channel, parent, null, new ContextInfo[0]); + } + else { + service.getChildren(parent.id, false, new IProcesses.DoneGetChildren() { + public void doneGetChildren(IToken token, Exception error, String[] context_ids) { + if (error != null) { + doneLoadChildren(channel, parent, error, null); + } + else if (context_ids == null || context_ids.length == 0) { + doneLoadChildren(channel, parent, null, new ContextInfo[0]); + } + else { + final List<ContextInfo> infos = new ArrayList<ContextInfo>(context_ids.length); + final Set<IToken> pending = new HashSet<IToken>(); + for (final String id : context_ids) { + final ContextInfo info = new ContextInfo(); + info.parent = parent; + info.id = id; + pending.add(service.getContext(id, new IProcesses.DoneGetContext() { + public void doneGetContext(IToken token, Exception error, ProcessContext context) { + if (context != null) { + info.name = context.getName(); + info.is_attached = context.isAttached(); + infos.add(info); + } + pending.remove(token); + if (!pending.isEmpty()) return; + doneLoadChildren(channel, parent, null, infos.toArray(new ContextInfo[infos.size()])); + } + })); + if (sysmon != null) { + pending.add(sysmon.getContext(id, new ISysMonitor.DoneGetContext() { + @Override + public void doneGetContext(IToken token, Exception error, SysMonitorContext context) { + if (context != null) { + info.pid = context.getPID(); + } + pending.remove(token); + if (!pending.isEmpty()) return; + doneLoadChildren(channel, parent, null, infos.toArray(new ContextInfo[infos.size()])); + } + })); + pending.add(sysmon.getCommandLine(id, new ISysMonitor.DoneGetCommandLine() { + @Override + public void doneGetCommandLine(IToken token, Exception error, String[] cmd_line) { + if (cmd_line != null) { + info.cmd_line = cmd_line; + } + pending.remove(token); + if (!pending.isEmpty()) return; + doneLoadChildren(channel, parent, null, infos.toArray(new ContextInfo[infos.size()])); + } + })); + } + } + } + } + }); + } + } + + private void loadContextChildren(final IChannel channel, final ContextInfo parent) { + final IRunControl service = channel.getRemoteService(IRunControl.class); + if (service == null) { + doneLoadChildren(channel, parent, new Exception("Peer does not support Run Control service"), null); + } + else if (!canHaveChildren(parent)) { + doneLoadChildren(channel, parent, null, new ContextInfo[0]); + } + else { + service.getChildren(parent.id, new IRunControl.DoneGetChildren() { + public void doneGetChildren(IToken token, Exception error, String[] context_ids) { + if (error != null) { + doneLoadChildren(channel, parent, error, null); + } + else if (context_ids != null && context_ids.length > 0) { + final List<ContextInfo> infos = new ArrayList<ContextInfo>(context_ids.length); + final Set<IToken> pending = new HashSet<IToken>(); + for (String id : context_ids) { + pending.add(service.getContext(id, new IRunControl.DoneGetContext() { + public void doneGetContext(IToken token, Exception error, RunControlContext context) { + if (context != null) { + ContextInfo info = new ContextInfo(); + info.parent = parent; + info.id = context.getID(); + info.name = context.getName(); + info.is_container = context.isContainer(); + info.has_state = context.hasState(); + info.is_attached = true; + infos.add(info); + } + pending.remove(token); + if (!pending.isEmpty()) return; + doneLoadChildren(channel, parent, null, infos.toArray(new ContextInfo[infos.size()])); + } + })); + } + } + else { + doneLoadChildren(channel, parent, null, new ContextInfo[0]); + } + } + }); + } + } + + private void doneLoadChildren(final IChannel channel, final ContextInfo parent, final Throwable error, final ContextInfo[] children) { + assert Protocol.isDispatchThread(); + assert error == null || children == null; + if (display == null) return; + final String state = getChannelState(channel); + display.asyncExec(new Runnable() { + public void run() { + if (ContextListControl.this.channel != channel) return; + assert parent.children_pending; + parent.children_pending = false; + if (state == null) { + parent.children = children; + parent.children_error = error; + if (parent.children_reload) { + loadChildren(parent); + } + } + else { + parent.children = null; + parent.children_reload = false; + } + channel_state = state; + updateItems(parent); + } + }); + } + + private String getChannelState(IChannel channel) { + if (channel == null) return "Not connected"; + switch (channel.getState()) { + case IChannel.STATE_OPENING: return "Connecting..."; + case IChannel.STATE_CLOSED: return "Disconnected"; + } + return null; + } + + private void onContextRemoved(final String id) { + if (display == null) return; + display.asyncExec(new Runnable() { + public void run() { + ContextInfo info = findInfo(root_info, id); + if (info != null && info.parent != null) loadChildren(info.parent); + } + }); + } + + private void onContextAdded(final String parent_id) { + if (display == null) return; + display.asyncExec(new Runnable() { + public void run() { + ContextInfo info = findInfo(root_info, parent_id); + if (info != null) loadChildren(info); + } + }); + } + + public String getFullName(ContextInfo info) { + if (info == null) return null; + String name = info.name; + if (name == null) name = info.id; + if (info.parent == root_info) return "/" + name; + if (info.parent == null) return null; + String path = getFullName(info.parent); + if (path == null) return null; + return path + '/' + name; + } + + private ContextInfo findInfoByFullName(ContextInfo parent, String name, boolean expand) { + if (name == null) return null; + if (name.startsWith("/")) return findInfoByFullName(root_info, name.substring(1), expand); + if (parent.children_pending) return null; + String head = name; + String tail = null; + int i = name.indexOf('/'); + if (i >= 0) { + head = name.substring(0, i); + tail = name.substring(i + 1); + } + ContextInfo[] children = parent.children; + if (children != null) { + for (ContextInfo info : children) { + if (head.equals(info.name)) { + if (tail == null) return info; + if (expand) { + TreeItem item = findItem(info); + if (item != null) item.setExpanded(true); + } + return findInfoByFullName(info, tail, expand); + } + } + } + else if (expand) { + loadChildren(parent); + } + return null; + } + + public ContextInfo findInfo(TreeItem item) { + assert Thread.currentThread() == display.getThread(); + if (item == null) return root_info; + return (ContextInfo)item.getData("TCFContextInfo"); + } + + public ContextInfo findInfo(ContextInfo parent, String id) { + assert Thread.currentThread() == display.getThread(); + if (id == null) return root_info; + if (id.equals(parent.id)) return parent; + ContextInfo[] children = parent.children; + if (children != null) { + for (ContextInfo info : children) { + ContextInfo found = findInfo(info, id); + if (found != null) return found; + } + } + return null; + } + + private TreeItem findItem(ContextInfo info) { + assert Thread.currentThread() == display.getThread(); + if (info == null) return null; + assert info.parent != null; + if (info.parent == root_info) { + TreeItem[] items = ctx_tree.getItems(); + for (TreeItem item : items) { + if (item.getData("TCFContextInfo") == info) return item; + } + return null; + } + TreeItem parent = findItem(info.parent); + if (parent == null) return null; + TreeItem[] items = parent.getItems(); + for (TreeItem item : items) { + if (item.getData("TCFContextInfo") == info) return item; + } + return null; + } + + private void fillItem(TreeItem item, ContextInfo info) { + assert Thread.currentThread() == display.getThread(); + Object data = item.getData("TCFContextInfo"); + if (data != null && data != info) item.removeAll(); + item.setData("TCFContextInfo", info); + StringBuffer bf = new StringBuffer(); + if (info.pid > 0) { + bf.append(info.pid); + bf.append(": "); + } + if (info.cmd_line != null && info.cmd_line.length > 0) { + for (String s : info.cmd_line) { + bf.append(' '); + bf.append(s); + } + } + else if (info.name != null) { + bf.append(info.name); + } + else { + bf.append(info.id); + } + item.setText(bf.toString()); + item.setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND)); + item.setImage(getImage(info)); + if (!canHaveChildren(info)) item.setItemCount(0); + else if (info.children == null || info.children_error != null) item.setItemCount(1); + else item.setItemCount(info.children.length); + } + + private boolean canHaveChildren(ContextInfo info) { + return !info.has_state && (info.is_container || info == root_info); + } + + private Image getImage(ContextInfo info) { + return ImageCache.getImage(info.has_state ? ImageCache.IMG_THREAD_UNKNOWN_STATE : ImageCache.IMG_PROCESS_RUNNING); + } + + public void setInitialSelection(String full_name) { + if (full_name == null) return; + if (full_name.length() == 0) return; + initial_selection = full_name; + ContextInfo info = findInfoByFullName(null, full_name, true); + if (info != null) { + TreeItem item = findItem(info); + if (item != null) { + ctx_tree.setSelection(item); + initial_selection = null; + } + } + } +} diff --git a/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/launch/ContextSelection.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/ContextSelection.java index 0cc2b0644..3337782ea 100644 --- a/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/launch/ContextSelection.java +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/ContextSelection.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011 Wind River Systems, Inc. and others. + * Copyright (c) 2011, 2013 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 @@ -8,18 +8,12 @@ * Contributors: * Wind River Systems - initial API and implementation *******************************************************************************/ -package org.eclipse.tcf.internal.cdt.launch; +package org.eclipse.tcf.internal.debug.ui.launch; public class ContextSelection { public String fPeerId; public String fContextId; + public String fContextFullName; + public String fContextName; public boolean fIsAttached; - public ContextSelection(String peerId, String contextId) { - this(peerId, contextId, true); - } - public ContextSelection(String peerId, String contextId, boolean isAttached) { - fPeerId = peerId; - fContextId = contextId; - fIsAttached = isAttached; - } } diff --git a/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/launch/ProcessSelectionDialog.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/ContextSelectionDialog.java index 15fa82bad..5c284d425 100644 --- a/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/launch/ProcessSelectionDialog.java +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/ContextSelectionDialog.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011 Wind River Systems, Inc. and others. + * Copyright (c) 2011, 2013 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 @@ -8,14 +8,10 @@ * Contributors: * Wind River Systems - initial API and implementation *******************************************************************************/ -package org.eclipse.tcf.internal.cdt.ui.launch; +package org.eclipse.tcf.internal.debug.ui.launch; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogConstants; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.ISelectionChangedListener; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.window.IShellProvider; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; @@ -25,34 +21,35 @@ import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.TreeItem; -import org.eclipse.tcf.internal.cdt.launch.ContextSelection; -import org.eclipse.tcf.internal.cdt.ui.launch.PeerListControl.PeerInfo; -import org.eclipse.tcf.internal.cdt.ui.launch.ProcessListControl.ProcessInfo; +import org.eclipse.tcf.internal.debug.ui.launch.PeerListControl.PeerInfo; +import org.eclipse.tcf.internal.debug.ui.launch.ContextListControl.ContextInfo; /** * Dialog to select a peer and context. */ -public class ProcessSelectionDialog extends Dialog { +public class ContextSelectionDialog extends Dialog { - private ContextSelection fSelection; - private ProcessListControl fContextList; + private final boolean processes; + private ContextSelection selection; + private ContextListControl context_list; - protected ProcessSelectionDialog(IShellProvider parentShell) { + public ContextSelectionDialog(IShellProvider parentShell, boolean processes) { super(parentShell); + this.processes = processes; } public void setSelection(ContextSelection selection) { - fSelection = selection; + this.selection = selection; } public ContextSelection getSelection() { - return fSelection; + return selection; } @Override - protected void configureShell(Shell newShell) { - newShell.setText("Select Peer and Context"); - super.configureShell(newShell); + protected void configureShell(Shell shell) { + shell.setText("Select Peer and Context"); + super.configureShell(shell); } @Override @@ -65,26 +62,19 @@ public class ProcessSelectionDialog extends Dialog { @Override protected Control createDialogArea(Composite parent) { Composite composite = (Composite) super.createDialogArea(parent); - new Label(composite, SWT.NONE).setText("TCF Peers:"); - final PeerListControl peerList = new PeerListControl(composite); - new Label(composite, SWT.NONE).setText("Contexts:"); - fContextList = new ProcessListControl(composite); - peerList.addSelectionChangedListener(new ISelectionChangedListener() { - public void selectionChanged(SelectionChangedEvent event) { - ISelection selection = event.getSelection(); - if (selection instanceof IStructuredSelection) { - IStructuredSelection ss = (IStructuredSelection) selection; - Object element = ss.getFirstElement(); - if (element instanceof PeerInfo) { - handlePeerSelected((PeerInfo) element); - } - } + new Label(composite, SWT.NONE).setText("Peers:"); + final PeerListControl peerList = new PeerListControl(composite) { + @Override + protected void onPeerSelected(PeerInfo info) { + handlePeerSelected(info); } - }); - fContextList.getTree().addSelectionListener(new SelectionAdapter() { + }; + new Label(composite, SWT.NONE).setText("Contexts:"); + context_list = new ContextListControl(composite, processes); + context_list.getTree().addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { - ProcessInfo contextInfo = fContextList.findProcessInfo((TreeItem) e.item); + ContextInfo contextInfo = context_list.findInfo((TreeItem) e.item); if (contextInfo != null) { handleContextSelected(contextInfo); } @@ -97,24 +87,29 @@ public class ProcessSelectionDialog extends Dialog { } } }); - if (fSelection.fContextId != null) { - fContextList.selectContext(fSelection.fContextId); + if (selection.fPeerId != null) { + peerList.setInitialSelection(selection.fPeerId); + } + if (selection.fContextFullName != null) { + context_list.setInitialSelection(selection.fContextFullName); } return composite; } private void updateButtonState() { - getButton(IDialogConstants.OK_ID).setEnabled(fSelection.fContextId != null); + getButton(IDialogConstants.OK_ID).setEnabled(selection.fContextId != null); } - protected void handleContextSelected(ProcessInfo contextInfo) { - fSelection.fContextId = contextInfo.id; + protected void handleContextSelected(ContextInfo info) { + selection.fContextId = info.id; + selection.fContextName = info.name; + selection.fContextFullName = context_list.getFullName(info); + selection.fIsAttached = info.is_attached; updateButtonState(); } - protected void handlePeerSelected(PeerInfo peerInfo) { - fSelection.fPeerId = peerInfo.id; - fContextList.setInput(peerInfo.peer); + protected void handlePeerSelected(PeerInfo info) { + selection.fPeerId = info.id; + context_list.setInput(info.peer); } - } diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/DownloadFileDialog.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/DownloadFileDialog.java new file mode 100644 index 000000000..dde60d720 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/DownloadFileDialog.java @@ -0,0 +1,400 @@ +/******************************************************************************* + * Copyright (c) 2013 Xilinx, 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: + * Xilinx - initial API and implementation + *******************************************************************************/ +package org.eclipse.tcf.internal.debug.ui.launch; + +import java.math.BigInteger; +import java.util.Map; + +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Image; +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.Control; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.MessageBox; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.eclipse.tcf.internal.debug.launch.TCFLaunchDelegate; +import org.eclipse.tcf.internal.debug.ui.ImageCache; +import org.eclipse.tcf.internal.debug.ui.model.TCFModel; +import org.eclipse.tcf.protocol.JSON; + +class DownloadFileDialog extends Dialog { + + private final Image image; + private final String peer_id; + private final Map<String,Object> map; + + private Text context_text; + private Text file_text; + private Text addr_text; + private Text size_text; + private Text offs_text; + private Button file_button; + private Button context_button; + private Button load_syms_button; + private Button relocate_button; + private Button download_button; + private Button set_pc_button; + private Button osa_button; + + DownloadFileDialog(Shell parentShell, String peer_id, Map<String,Object> map) { + super(parentShell); + this.image = ImageCache.getImage(ImageCache.IMG_DOWNLOAD_TAB); + this.peer_id = peer_id; + this.map = map; + } + + @Override + protected void configureShell(Shell shell) { + super.configureShell(shell); + shell.setText("Download File"); //$NON-NLS-1$ + shell.setImage(image); + } + + @Override + protected void createButtonsForButtonBar(Composite parent) { + createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); + createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); + updateButtons(); + } + + @Override + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite)super.createDialogArea(parent); + createFileFields(composite); + setData(); + composite.setSize(composite.computeSize(SWT.DEFAULT, SWT.DEFAULT)); + return composite; + } + + private void createFileFields(Composite parent) { + Font font = parent.getFont(); + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(3, false); + composite.setFont(font); + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + Label context_label = new Label(composite, SWT.NONE); + context_label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); + context_label.setFont(font); + context_label.setText("Context:"); //$NON-NLS-1$ + + context_text = new Text(composite, SWT.SINGLE | SWT.BORDER); + GridData gd = new GridData(GridData.FILL_HORIZONTAL); + gd.widthHint = 400; + context_text.setLayoutData(gd); + context_text.setFont(font); + + context_text.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + updateButtons(); + } + }); + + context_button = new Button(composite, SWT.PUSH); + context_button.setText("Select..."); //$NON-NLS-1$ + context_button.setFont(font); + context_button.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + context_button.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + String context = context_text.getText().trim(); + ContextSelection selection = new ContextSelection(); + selection.fPeerId = peer_id; + selection.fContextFullName = context; + ContextSelectionDialog diag = new ContextSelectionDialog(DownloadFileDialog.this, false); + diag.setSelection(selection); + if (diag.open() == Window.OK) { + selection = diag.getSelection(); + context_text.setText(selection.fContextFullName); + } + } + }); + + Label file_label = new Label(composite, SWT.NONE); + file_label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); + file_label.setFont(font); + file_label.setText("File:"); //$NON-NLS-1$ + + file_text = new Text(composite, SWT.SINGLE | SWT.BORDER); + file_text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + file_text.setFont(font); + + file_text.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + updateButtons(); + } + }); + + file_button = new Button(composite, SWT.PUSH); + file_button.setText("Browse..."); //$NON-NLS-1$ + file_button.setFont(font); + file_button.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + file_button.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + String path = file_text.getText().trim(); + if (path.length() == 0) path = ResourcesPlugin.getWorkspace().getRoot().getLocation().toOSString(); + FileDialog dialog = new FileDialog(getShell(), SWT.NONE); + dialog.setFilterPath(path); + path = dialog.open(); + if (path != null) file_text.setText(path); + } + }); + + load_syms_button = new Button(composite, SWT.CHECK); + load_syms_button.setText("Load symbols"); + gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = 3; + load_syms_button.setLayoutData(gd); + load_syms_button.setFont(font); + load_syms_button.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent evt) { + updateButtons(); + } + }); + load_syms_button.setEnabled(true); + + relocate_button = new Button(composite, SWT.CHECK); + relocate_button.setText("Relocate the file"); + gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = 3; + relocate_button.setLayoutData(gd); + relocate_button.setFont(font); + relocate_button.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent evt) { + updateButtons(); + } + }); + relocate_button.setEnabled(true); + Composite rel_group = createRelocateGroup(composite); + gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = 3; + rel_group.setLayoutData(gd); + + download_button = new Button(composite, SWT.CHECK); + download_button.setText("Download the file into the context memory"); + gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = 3; + download_button.setLayoutData(gd); + download_button.setFont(font); + download_button.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent evt) { + updateButtons(); + } + }); + download_button.setEnabled(true); + + set_pc_button = new Button(composite, SWT.CHECK); + set_pc_button.setText("Set PC to program entry address"); + gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = 3; + set_pc_button.setLayoutData(gd); + set_pc_button.setFont(font); + set_pc_button.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent evt) { + updateButtons(); + } + }); + set_pc_button.setEnabled(true); + + osa_button = new Button(composite, SWT.CHECK); + osa_button.setText("Enable OS awarennes - the file is an OS kernel"); + gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = 3; + osa_button.setLayoutData(gd); + osa_button.setFont(font); + osa_button.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent evt) { + updateButtons(); + } + }); + osa_button.setEnabled(true); + } + + private Composite createRelocateGroup(Composite parent) { + Font font = parent.getFont(); + + Group group = new Group(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.verticalSpacing = 0; + layout.numColumns = 2; + group.setLayout(layout); + group.setLayoutData(new GridData(GridData.FILL_BOTH)); + group.setFont(font); + group.setText("File location in the context memory"); + + Label addr_label = new Label(group, SWT.WRAP); + addr_label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); + addr_label.setFont(font); + addr_label.setText("Address:"); + + addr_text = new Text(group, SWT.SINGLE | SWT.BORDER); + addr_text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + addr_text.setFont(font); + + Label size_label = new Label(group, SWT.WRAP); + size_label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); + size_label.setFont(font); + size_label.setText("Size:"); + + size_text = new Text(group, SWT.SINGLE | SWT.BORDER); + size_text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + size_text.setFont(font); + + Label offset_label = new Label(group, SWT.WRAP); + offset_label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); + offset_label.setFont(font); + offset_label.setText("File offset:"); + + offs_text = new Text(group, SWT.SINGLE | SWT.BORDER); + offs_text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + offs_text.setFont(font); + + return group; + } + + private String toHex(Number n) { + if (n == null) return null; + BigInteger x = JSON.toBigInteger(n); + String s = x.toString(16); + int l = 16 - s.length(); + if (l < 0) l = 0; + if (l > 16) l = 16; + return "0x0000000000000000".substring(0, 2 + l) + s; + } + + private void setString(Text text, String key) { + String s = (String)map.get(key); + if (s == null) s = ""; + text.setText(s); + } + + private void setBoolean(Button btn, String key) { + Boolean b = (Boolean)map.get(key); + if (b == null) btn.setSelection(false); + else btn.setSelection(b.booleanValue()); + } + + private void setNumber(Text text, String key) { + Number n = (Number)map.get(key); + if (n == null) text.setText(""); + else text.setText(toHex(n)); + } + + private void setData() { + setString(context_text, TCFLaunchDelegate.FILES_CONTEXT_FULL_NAME); + setString(file_text, TCFLaunchDelegate.FILES_FILE_NAME); + setBoolean(load_syms_button, TCFLaunchDelegate.FILES_LOAD_SYMBOLS); + setBoolean(relocate_button, TCFLaunchDelegate.FILES_RELOCATE); + setBoolean(download_button, TCFLaunchDelegate.FILES_DOWNLOAD); + setBoolean(set_pc_button, TCFLaunchDelegate.FILES_SET_PC); + setBoolean(osa_button, TCFLaunchDelegate.FILES_ENABLE_OSA); + setNumber(addr_text, TCFLaunchDelegate.FILES_ADDRESS); + setNumber(offs_text, TCFLaunchDelegate.FILES_OFFSET); + setNumber(size_text, TCFLaunchDelegate.FILES_SIZE); + updateButtons(); + } + + private void getBoolean(Button btn, String key) { + boolean b = btn.getSelection(); + if (!b) { + map.remove(key); + } + else { + map.put(key, Boolean.TRUE); + } + } + + private void getString(Text text, String key) { + String s = text.getText().trim(); + if (s == null || s.length() == 0) { + map.remove(key); + } + else { + map.put(key, s); + } + } + + private void getNumber(Text text, String key) { + String s = text.getText().trim(); + if (s == null || s.length() == 0) { + map.remove(key); + } + else if (s.startsWith("0x")) { + map.put(key, new BigInteger(s.substring(2), 16)); + } + else { + map.put(key, new BigInteger(s)); + } + } + + private void getData() { + getString(context_text, TCFLaunchDelegate.FILES_CONTEXT_FULL_NAME); + getString(file_text, TCFLaunchDelegate.FILES_FILE_NAME); + getBoolean(load_syms_button, TCFLaunchDelegate.FILES_LOAD_SYMBOLS); + getBoolean(relocate_button, TCFLaunchDelegate.FILES_RELOCATE); + getBoolean(download_button, TCFLaunchDelegate.FILES_DOWNLOAD); + getBoolean(set_pc_button, TCFLaunchDelegate.FILES_SET_PC); + getBoolean(osa_button, TCFLaunchDelegate.FILES_ENABLE_OSA); + getNumber(addr_text, TCFLaunchDelegate.FILES_ADDRESS); + getNumber(offs_text, TCFLaunchDelegate.FILES_OFFSET); + getNumber(size_text, TCFLaunchDelegate.FILES_SIZE); + } + + private void updateButtons() { + Button btn = getButton(IDialogConstants.OK_ID); + if (btn != null && context_text != null && file_text != null) { + String context = context_text.getText().trim(); + String file = file_text.getText().trim(); + btn.setEnabled(context.length() > 0 && file.length() > 0); + } + if (relocate_button != null) { + boolean reloc = relocate_button.getSelection(); + addr_text.setEnabled(reloc); + size_text.setEnabled(reloc); + offs_text.setEnabled(reloc); + } + } + + @Override + protected void okPressed() { + try { + getData(); + } + catch (Throwable x) { + MessageBox mb = new MessageBox(getShell(), SWT.ICON_ERROR | SWT.OK); + mb.setText("Invalid data"); //$NON-NLS-1$ + mb.setMessage(TCFModel.getErrorMessage(x, true)); + mb.open(); + return; + } + super.okPressed(); + } +} diff --git a/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/launch/FileSystemBrowserControl.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/FileSystemBrowserControl.java index e6ee9453a..ce8da20bf 100644 --- a/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/launch/FileSystemBrowserControl.java +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/FileSystemBrowserControl.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011 Wind River Systems, Inc. and others. + * Copyright (c) 2011, 2013 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 @@ -8,7 +8,7 @@ * Contributors: * Wind River Systems - initial API and implementation *******************************************************************************/ -package org.eclipse.tcf.internal.cdt.ui.launch; +package org.eclipse.tcf.internal.debug.ui.launch; import java.util.ArrayList; import java.util.Arrays; diff --git a/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/launch/PeerListControl.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/PeerListControl.java index 69174d524..82f7aadb8 100644 --- a/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/launch/PeerListControl.java +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/PeerListControl.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011 Wind River Systems, Inc. and others. + * Copyright (c) 2011, 2013 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 @@ -8,14 +8,12 @@ * Contributors: * Wind River Systems - initial API and implementation *******************************************************************************/ -package org.eclipse.tcf.internal.cdt.ui.launch; +package org.eclipse.tcf.internal.debug.ui.launch; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; -import java.util.List; import java.util.Map; -import java.util.Set; import org.eclipse.core.runtime.ListenerList; import org.eclipse.jface.viewers.ISelection; @@ -42,10 +40,11 @@ import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeColumn; import org.eclipse.swt.widgets.TreeItem; -import org.eclipse.tcf.internal.cdt.ui.Activator; -import org.eclipse.tcf.internal.cdt.ui.ImageCache; +import org.eclipse.tcf.internal.debug.launch.TCFUserDefPeer; +import org.eclipse.tcf.internal.debug.ui.Activator; +import org.eclipse.tcf.internal.debug.ui.ImageCache; +import org.eclipse.tcf.internal.debug.ui.model.TCFModel; import org.eclipse.tcf.protocol.IChannel; -import org.eclipse.tcf.protocol.IChannel.IChannelListener; import org.eclipse.tcf.protocol.IPeer; import org.eclipse.tcf.protocol.Protocol; import org.eclipse.tcf.services.ILocator; @@ -56,21 +55,22 @@ public class PeerListControl implements ISelectionProvider { private Tree peer_tree; private final PeerInfo peer_info = new PeerInfo(); private Display display; - private final ListenerList fSelectionListeners = new ListenerList(ListenerList.IDENTITY); - private String fInitialPeerId = "*"; + private final ListenerList selection_listeners = new ListenerList(ListenerList.IDENTITY); + private String initial_peer_id; + + public static class PeerInfo { + public String id; + public IPeer peer; - static class PeerInfo { PeerInfo parent; - int index; - String id; Map<String,String> attrs; PeerInfo[] children; boolean children_pending; Throwable children_error; - IPeer peer; IChannel channel; ILocator locator; LocatorListener listener; + Runnable item_update; } private class LocatorListener implements ILocator.LocatorListener { @@ -89,17 +89,11 @@ public class PeerListControl implements ISelectionProvider { public void run() { if (parent.children_error != null) return; PeerInfo[] arr = parent.children; - String agentId = attrs.get(IPeer.ATTR_AGENT_ID); - for (PeerInfo p : arr) { - assert !p.id.equals(id); - if (agentId != null && agentId.equals(p.attrs.get(IPeer.ATTR_AGENT_ID))) - return; - } + for (PeerInfo p : arr) assert !p.id.equals(id); PeerInfo[] buf = new PeerInfo[arr.length + 1]; System.arraycopy(arr, 0, buf, 0, arr.length); PeerInfo info = new PeerInfo(); info.parent = parent; - info.index = arr.length; info.id = id; info.attrs = attrs; info.peer = peer; @@ -147,7 +141,6 @@ public class PeerListControl implements ISelectionProvider { }); } else { - arr[i].index = j; buf[j++] = arr[i]; } } @@ -193,8 +186,26 @@ public class PeerListControl implements ISelectionProvider { createPeerListArea(parent); } - public void setInitialSelectedPeerId(String peerId) { - fInitialPeerId = peerId; + public void setInitialSelection(String id) { + if (id == null) return; + if (id.length() == 0) return; + PeerInfo info = findPeerInfo(id); + if (info != null) { + setSelection(new StructuredSelection(info)); + fireSelectionChangedEvent(); + onPeerSelected(info); + } + else { + String p = id; + for (;;) { + int i = p.lastIndexOf('/'); + if (i < 0) break; + p = p.substring(0, i); + TreeItem item = findItem(p); + if (item != null) item.setExpanded(true); + } + initial_peer_id = id; + } } public Tree getTree() { @@ -204,20 +215,18 @@ public class PeerListControl implements ISelectionProvider { private void createPeerListArea(Composite parent) { Font font = parent.getFont(); Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(2, false); composite.setFont(font); - GridLayout layout = new GridLayout(1, false); - layout.marginWidth = 0; - layout.marginHeight = 0; composite.setLayout(layout); - composite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true)); + composite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true, 2, 1)); peer_tree = new Tree(composite, SWT.VIRTUAL | SWT.BORDER | SWT.SINGLE); GridData gd = new GridData(GridData.FILL_BOTH); - gd.heightHint = 80; - gd.minimumWidth = 400; + gd.minimumHeight = 150; + gd.minimumWidth = 470; peer_tree.setLayoutData(gd); - for (int i = 0; i < 5; i++) { + for (int i = 0; i < 6; i++) { TreeColumn column = new TreeColumn(peer_tree, SWT.LEAD, i); column.setMoveable(true); switch (i) { @@ -230,14 +239,18 @@ public class PeerListControl implements ISelectionProvider { column.setWidth(100); break; case 2: + column.setText("User"); + column.setWidth(100); + break; + case 3: column.setText("Transport"); column.setWidth(60); break; - case 3: + case 4: column.setText("Host"); column.setWidth(100); break; - case 4: + case 5: column.setText("Port"); column.setWidth(40); break; @@ -247,6 +260,7 @@ public class PeerListControl implements ISelectionProvider { peer_tree.setHeaderVisible(true); peer_tree.setFont(font); peer_tree.addListener(SWT.SetData, new Listener() { + @Override public void handleEvent(Event event) { TreeItem item = (TreeItem)event.item; PeerInfo info = findPeerInfo(item); @@ -255,23 +269,52 @@ public class PeerListControl implements ISelectionProvider { } else { fillItem(item, info); + onPeerListChanged(); } } }); + peer_tree.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetDefaultSelected(SelectionEvent e) { + TreeItem[] selections = peer_tree.getSelection(); + if (selections.length == 0) return; + final PeerInfo info = findPeerInfo(selections[0]); + if (info == null) return; + new PeerPropsDialog(peer_tree.getShell(), getImage(info), info.attrs, + info.peer instanceof TCFUserDefPeer).open(); + if (!(info.peer instanceof TCFUserDefPeer)) return; + Protocol.invokeLater(new Runnable() { + public void run() { + ((TCFUserDefPeer)info.peer).updateAttributes(info.attrs); + TCFUserDefPeer.savePeers(); + } + }); + } + @Override + public void widgetSelected(SelectionEvent e) { + fireSelectionChangedEvent(); + TreeItem[] selections = peer_tree.getSelection(); + if (selections.length > 0) { + assert selections.length == 1; + PeerInfo info = findPeerInfo(selections[0]); + if (info != null) { + initial_peer_id = null; + onPeerSelected(info); + } + } + onPeerListChanged(); + } + }); peer_tree.addTreeListener(new TreeListener() { + @Override public void treeCollapsed(TreeEvent e) { updateItems((TreeItem)e.item, false); } + @Override public void treeExpanded(TreeEvent e) { updateItems((TreeItem)e.item, true); } }); - peer_tree.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - fireSelectionChangedEvent(); - } - }); } private void handleDispose() { @@ -322,7 +365,7 @@ public class PeerListControl implements ISelectionProvider { else { final IChannel channel = parent.peer.openChannel(); parent.channel = channel; - parent.channel.addChannelListener(new IChannelListener() { + parent.channel.addChannelListener(new IChannel.IChannelListener() { boolean opened = false; boolean closed = false; public void congestionLevel(int level) { @@ -357,8 +400,7 @@ public class PeerListControl implements ISelectionProvider { opened = true; parent.locator = parent.channel.getRemoteService(ILocator.class); if (parent.locator == null) { - doneLoadChildren(parent, new Exception("Service not supported: " + ILocator.NAME), null); - parent.channel.close(); + parent.channel.terminate(new Exception("Service not supported: " + ILocator.NAME)); } else { doneLoadChildren(parent, null, createLocatorListener(parent)); @@ -373,21 +415,16 @@ public class PeerListControl implements ISelectionProvider { private PeerInfo[] createLocatorListener(PeerInfo peer) { assert Protocol.isDispatchThread(); Map<String,IPeer> map = peer.locator.getPeers(); - List<PeerInfo> filteredPeers = new ArrayList<PeerInfo>(); - Set<String> agentIds = new HashSet<String>(); + PeerInfo[] buf = new PeerInfo[map.size()]; + int n = 0; for (IPeer p : map.values()) { - String agentID = p.getAgentID(); - if (agentID != null && agentIds.add(agentID)) { - PeerInfo info = new PeerInfo(); - info.parent = peer; - info.index = filteredPeers.size(); - info.id = p.getID(); - info.attrs = new HashMap<String,String>(p.getAttributes()); - info.peer = p; - filteredPeers.add(info); - } + PeerInfo info = new PeerInfo(); + info.parent = peer; + info.id = p.getID(); + info.attrs = new HashMap<String,String>(p.getAttributes()); + info.peer = p; + buf[n++] = info; } - PeerInfo[] buf = filteredPeers.toArray(new PeerInfo[filteredPeers.size()]); peer.listener = new LocatorListener(peer); peer.locator.addListener(peer.listener); return buf; @@ -409,6 +446,39 @@ public class PeerListControl implements ISelectionProvider { }); } + private ArrayList<PeerInfo> filterPeerList(PeerInfo parent, boolean expanded) { + ArrayList<PeerInfo> lst = new ArrayList<PeerInfo>(); + HashMap<String,PeerInfo> local_agents = new HashMap<String,PeerInfo>(); + HashSet<String> ids = new HashSet<String>(); + for (PeerInfo p : parent.children) { + String id = p.attrs.get(IPeer.ATTR_AGENT_ID); + if (id == null) continue; + if (!"TCP".equals(p.attrs.get(IPeer.ATTR_TRANSPORT_NAME))) continue; + if (!"127.0.0.1".equals(p.attrs.get(IPeer.ATTR_IP_HOST))) continue; + local_agents.put(id, p); + ids.add(p.id); + } + for (PeerInfo p : parent.children) { + PeerInfo i = local_agents.get(p.attrs.get(IPeer.ATTR_AGENT_ID)); + if (i != null && i != p) continue; + lst.add(p); + } + if (parent != peer_info && expanded) { + for (PeerInfo p : peer_info.children) { + if (p.peer instanceof TCFUserDefPeer && !ids.contains(p.id)) { + PeerInfo x = new PeerInfo(); + x.parent = parent; + x.id = p.id; + x.attrs = p.attrs; + x.peer = p.peer; + ids.add(x.id); + lst.add(x); + } + } + } + return lst; + } + private void updateItems(TreeItem parent_item, boolean reload) { final PeerInfo parent_info = findPeerInfo(parent_item); if (parent_info == null) { @@ -429,140 +499,158 @@ public class PeerListControl implements ISelectionProvider { private void updateItems(final PeerInfo parent) { if (display == null) return; assert Thread.currentThread() == display.getThread(); - TreeItem[] items = null; - boolean expanded = true; - if (parent.children == null || parent.children_error != null) { - if (parent == peer_info) { - peer_tree.setItemCount(1); - items = peer_tree.getItems(); - } - else { - TreeItem item = findItem(parent); - if (item == null) return; - expanded = item.getExpanded(); - item.setItemCount(1); - items = item.getItems(); - } - assert items.length == 1; - items[0].removeAll(); - if (parent.children_pending) { - items[0].setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND)); - items[0].setText("Connecting..."); - } - else if (parent.children_error != null) { - String msg = parent.children_error.getMessage(); - if (msg == null) msg = parent.children_error.getClass().getName(); - else msg = msg.replace('\n', ' '); - items[0].setForeground(display.getSystemColor(SWT.COLOR_RED)); - items[0].setText(msg); - } - else if (expanded) { - loadChildren(parent); - items[0].setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND)); - items[0].setText("Connecting..."); - } - else { - Protocol.invokeAndWait(new Runnable() { - public void run() { - disconnectPeer(parent); + parent.item_update = new Runnable() { + public void run() { + if (display == null) return; + if (parent.item_update != this) return; + if (Thread.currentThread() != display.getThread()) { + display.asyncExec(this); + return; + } + parent.item_update = null; + TreeItem[] items = null; + boolean expanded = true; + if (parent.children == null || parent.children_error != null) { + if (parent == peer_info) { + peer_tree.setItemCount(1); + items = peer_tree.getItems(); } - }); - items[0].setText(""); - } - int n = peer_tree.getColumnCount(); - for (int i = 1; i < n; i++) items[0].setText(i, ""); - items[0].setImage((Image)null); - } - else { - PeerInfo[] arr = parent.children; - if (parent == peer_info) { - peer_tree.setItemCount(arr.length); - items = peer_tree.getItems(); - } - else { - TreeItem item = findItem(parent); - if (item == null) return; - expanded = item.getExpanded(); - item.setItemCount(expanded ? arr.length : 1); - items = item.getItems(); - } - if (expanded) { - assert items.length == arr.length; - for (int i = 0; i < items.length; i++) fillItem(items[i], arr[i]); - if (fInitialPeerId != null && items.length > 0) { - if ("*".equals(fInitialPeerId)) { - fInitialPeerId = null; - peer_tree.setSelection(items[0]); - fireSelectionChangedEvent(); - } else { - int i = 0; - for (PeerInfo peerInfo : arr) { - if (fInitialPeerId.equals(peerInfo.id)) { - fInitialPeerId = null; - peer_tree.setSelection(items[i]); - fireSelectionChangedEvent(); - break; + else { + TreeItem item = findItem(parent); + if (item == null) return; + expanded = item.getExpanded(); + item.setItemCount(1); + items = item.getItems(); + } + assert items.length == 1; + if (parent.children_pending) { + items[0].setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND)); + fillItem(items[0], "Connecting..."); + } + else if (parent.children_error != null) { + String msg = TCFModel.getErrorMessage(parent.children_error, false); + items[0].setForeground(display.getSystemColor(SWT.COLOR_RED)); + fillItem(items[0], msg); + } + else if (expanded) { + loadChildren(parent); + items[0].setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND)); + fillItem(items[0], "Connecting..."); + } + else { + Protocol.invokeAndWait(new Runnable() { + public void run() { + disconnectPeer(parent); } - i++; - } + }); + fillItem(items[0], ""); } } - } - else { - Protocol.invokeAndWait(new Runnable() { - public void run() { - disconnectPeer(parent); + else { + ArrayList<PeerInfo> lst = null; + if (parent == peer_info) { + lst = filterPeerList(parent, expanded); + peer_tree.setItemCount(lst.size() > 0 ? lst.size() : 1); + items = peer_tree.getItems(); } - }); - items[0].setText(""); - int n = peer_tree.getColumnCount(); - for (int i = 1; i < n; i++) items[0].setText(i, ""); + else { + TreeItem item = findItem(parent); + if (item == null) return; + expanded = item.getExpanded(); + lst = filterPeerList(parent, expanded); + item.setItemCount(expanded && lst.size() > 0 ? lst.size() : 1); + items = item.getItems(); + } + if (expanded && lst.size() > 0) { + assert items.length == lst.size(); + for (int i = 0; i < items.length; i++) fillItem(items[i], lst.get(i)); + } + else if (expanded) { + fillItem(items[0], "No peers"); + } + else { + Protocol.invokeAndWait(new Runnable() { + public void run() { + disconnectPeer(parent); + } + }); + fillItem(items[0], ""); + } + } + onPeerListChanged(); + if (initial_peer_id != null) { + setInitialSelection(initial_peer_id); + } } - } + }; + if (parent.children_pending) parent.item_update.run(); + else Protocol.invokeLater(200, parent.item_update); } - public PeerInfo findPeerInfo(String peerId) { - return findPeerInfo(peer_info, peerId); - } - - private PeerInfo findPeerInfo(PeerInfo parent, String peerId) { - if (peerId.equals(parent.id)) return parent; - PeerInfo[] children = parent.children; - if (children == null) return null; - for (PeerInfo child : children) { - PeerInfo info = findPeerInfo(child, peerId); - if (info != null) return info; + public TreeItem findItem(String path) { + assert Thread.currentThread() == display.getThread(); + if (path == null) return null; + int z = path.lastIndexOf('/'); + if (z < 0) { + int n = peer_tree.getItemCount(); + for (int i = 0; i < n; i++) { + TreeItem x = peer_tree.getItem(i); + PeerInfo p = (PeerInfo)x.getData("TCFPeerInfo"); + if (p != null && p.id.equals(path)) return x; + } + } + else { + TreeItem y = findItem(path.substring(0, z)); + if (y == null) return null; + String id = path.substring(z + 1); + int n = y.getItemCount(); + for (int i = 0; i < n; i++) { + TreeItem x = y.getItem(i); + PeerInfo p = (PeerInfo)x.getData("TCFPeerInfo"); + if (p != null && p.id.equals(id)) return x; + } } return null; } - public PeerInfo findPeerInfo(TreeItem item) { - assert Thread.currentThread() == display.getThread(); - if (item == null) return peer_info; - TreeItem parent = item.getParentItem(); - PeerInfo info = findPeerInfo(parent); - if (info == null) return null; - if (info.children == null) return null; - if (info.children_error != null) return null; - int i = parent == null ? peer_tree.indexOf(item) : parent.indexOf(item); - if (i < 0 || i >= info.children.length) return null; - assert info.children[i].index == i; - return info.children[i]; - } - - private TreeItem findItem(PeerInfo info) { + public TreeItem findItem(PeerInfo info) { if (info == null) return null; assert info.parent != null; if (info.parent == peer_info) { int n = peer_tree.getItemCount(); - if (info.index >= n) return null; - return peer_tree.getItem(info.index); + for (int i = 0; i < n; i++) { + TreeItem x = peer_tree.getItem(i); + if (x.getData("TCFPeerInfo") == info) return x; + } } - TreeItem i = findItem(info.parent); + else { + TreeItem y = findItem(info.parent); + if (y == null) return null; + int n = y.getItemCount(); + for (int i = 0; i < n; i++) { + TreeItem x = y.getItem(i); + if (x.getData("TCFPeerInfo") == info) return x; + } + } + return null; + } + + public String getPath(PeerInfo info) { + if (info == peer_info) return ""; + if (info.parent == peer_info) return info.id; + return getPath(info.parent) + "/" + info.id; + } + + public PeerInfo findPeerInfo(String path) { + TreeItem i = findItem(path); if (i == null) return null; - int n = i.getItemCount(); - if (info.index >= n) return null; - return i.getItem(info.index); + return (PeerInfo)i.getData("TCFPeerInfo"); + } + + private PeerInfo findPeerInfo(TreeItem item) { + assert Thread.currentThread() == display.getThread(); + if (item == null) return peer_info; + return (PeerInfo)item.getData("TCFPeerInfo"); } private void fillItem(TreeItem item, PeerInfo info) { @@ -570,29 +658,39 @@ public class PeerListControl implements ISelectionProvider { Object data = item.getData("TCFPeerInfo"); if (data != null && data != info) item.removeAll(); item.setData("TCFPeerInfo", info); - String text[] = new String[5]; + String text[] = new String[6]; text[0] = info.attrs.get(IPeer.ATTR_NAME); text[1] = info.attrs.get(IPeer.ATTR_OS_NAME); - text[2] = info.attrs.get(IPeer.ATTR_TRANSPORT_NAME); - text[3] = info.attrs.get(IPeer.ATTR_IP_HOST); - text[4] = info.attrs.get(IPeer.ATTR_IP_PORT); + text[2] = info.attrs.get(IPeer.ATTR_USER_NAME); + text[3] = info.attrs.get(IPeer.ATTR_TRANSPORT_NAME); + text[4] = info.attrs.get(IPeer.ATTR_IP_HOST); + text[5] = info.attrs.get(IPeer.ATTR_IP_PORT); for (int i = 0; i < text.length; i++) { if (text[i] == null) text[i] = ""; } item.setText(text); item.setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND)); - item.setImage(ImageCache.getImage(getImageName(info))); + item.setImage(getImage(info)); if (!canHaveChildren(info)) item.setItemCount(0); else if (info.children == null || info.children_error != null) item.setItemCount(1); else item.setItemCount(info.children.length); } - private String getImageName(PeerInfo info) { - return ImageCache.IMG_TARGET_TAB; + private void fillItem(TreeItem item, String text) { + item.setText(text); + item.setData("TCFPeerInfo", null); + int n = peer_tree.getColumnCount(); + for (int i = 1; i < n; i++) item.setText(i, ""); + item.setImage((Image)null); + item.removeAll(); + } + + private Image getImage(PeerInfo info) { + return ImageCache.getImage(ImageCache.IMG_TARGET_TAB); } public void addSelectionChangedListener(ISelectionChangedListener listener) { - fSelectionListeners .add(listener); + selection_listeners.add(listener); } public ISelection getSelection() { @@ -606,7 +704,7 @@ public class PeerListControl implements ISelectionProvider { } public void removeSelectionChangedListener(ISelectionChangedListener listener) { - fSelectionListeners.remove(listener); + selection_listeners.remove(listener); } public void setSelection(ISelection selection) { @@ -626,14 +724,20 @@ public class PeerListControl implements ISelectionProvider { private void fireSelectionChangedEvent() { SelectionChangedEvent event = new SelectionChangedEvent(this, getSelection()); - Object[] listeners = fSelectionListeners.getListeners(); + Object[] listeners = selection_listeners.getListeners(); for (Object listener : listeners) { try { ((ISelectionChangedListener) listener).selectionChanged(event); - } catch (Exception e) { + } + catch (Exception e) { Activator.log(e); } } } + protected void onPeerListChanged() { + } + + protected void onPeerSelected(PeerInfo info) { + } } diff --git a/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/launch/RemoteFileSelectionDialog.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/RemoteFileSelectionDialog.java index 23af441d2..ca8b5e949 100644 --- a/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/launch/RemoteFileSelectionDialog.java +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/RemoteFileSelectionDialog.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011 Wind River Systems, Inc. and others. + * Copyright (c) 2011, 2013 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 @@ -8,7 +8,7 @@ * Contributors: * Wind River Systems - initial API and implementation *******************************************************************************/ -package org.eclipse.tcf.internal.cdt.ui.launch; +package org.eclipse.tcf.internal.debug.ui.launch; import org.eclipse.core.runtime.Path; import org.eclipse.jface.dialogs.Dialog; @@ -27,7 +27,7 @@ import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import org.eclipse.swt.widgets.TreeItem; -import org.eclipse.tcf.internal.cdt.ui.launch.FileSystemBrowserControl.FileInfo; +import org.eclipse.tcf.internal.debug.ui.launch.FileSystemBrowserControl.FileInfo; import org.eclipse.tcf.protocol.IPeer; /** @@ -41,7 +41,7 @@ public class RemoteFileSelectionDialog extends Dialog { private boolean fForSave; private Text fFileNameText; - protected RemoteFileSelectionDialog(IShellProvider parentShell, int style) { + public RemoteFileSelectionDialog(IShellProvider parentShell, int style) { super(parentShell); setShellStyle(getShellStyle() | SWT.RESIZE); fForSave = (style & SWT.SAVE) != 0; diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFDownloadTab.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFDownloadTab.java new file mode 100644 index 000000000..e31dd31a1 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFDownloadTab.java @@ -0,0 +1,361 @@ +/******************************************************************************* + * Copyright (c) 2013 Xilinx, 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: + * Xilinx - initial API and implementation + *******************************************************************************/ +package org.eclipse.tcf.internal.debug.ui.launch; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; +import org.eclipse.debug.ui.AbstractLaunchConfigurationTab; +import org.eclipse.debug.ui.ILaunchConfigurationTab; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.Viewer; +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.graphics.Font; +import org.eclipse.swt.graphics.Image; +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.Label; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.MenuItem; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.tcf.internal.debug.launch.TCFLaunchDelegate; +import org.eclipse.tcf.internal.debug.ui.Activator; +import org.eclipse.tcf.internal.debug.ui.ImageCache; +import org.eclipse.tcf.protocol.JSON; +import org.eclipse.tcf.util.TCFTask; +import org.eclipse.ui.ISharedImages; +import org.eclipse.ui.PlatformUI; + +public class TCFDownloadTab extends AbstractLaunchConfigurationTab { + + private TableViewer viewer; + private Button button_add; + private Button button_edit; + private Button button_remove; + private MenuItem item_add; + private MenuItem item_edit; + private MenuItem item_remove; + + private static final String[] column_ids = { + TCFLaunchDelegate.FILES_CONTEXT_FULL_NAME, + TCFLaunchDelegate.FILES_FILE_NAME, + }; + + private static final int[] column_size = { + 300, + 400, + }; + + private final List<Map<String,Object>> list = new ArrayList<Map<String,Object>>(); + + private static final String TAB_ID = "org.eclipse.tcf.launch.downloadTab"; //$NON-NLS-1$ + + private class FileListContentProvider implements IStructuredContentProvider { + + public Object[] getElements(Object input) { + return list.toArray(new Map[list.size()]); + } + + public void inputChanged(Viewer viewer, Object old_input, Object new_input) { + } + + public void dispose() { + } + } + + private class FileListLabelProvider extends LabelProvider implements ITableLabelProvider { + + public Image getColumnImage(Object element, int column) { + if (column == 0) return ImageCache.getImage(ImageCache.IMG_ATTRIBUTE); + return null; + } + + public String getColumnText(Object element, int column) { + @SuppressWarnings("unchecked") + Map<String,String> e = (Map<String,String>)element; + Object o = e.get(column_ids[column]); + if (o == null) return ""; //$NON-NLS-1$ + return o.toString(); + } + } + + private Exception init_error; + + public String getName() { + return "Download"; //$NON-NLS-1$ + } + + @Override + public Image getImage() { + return ImageCache.getImage(ImageCache.IMG_DOWNLOAD_TAB); + } + + @Override + public String getId() { + return TAB_ID; + } + + public void createControl(Composite parent) { + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(1, false); + composite.setFont(parent.getFont()); + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true, 1, 1)); + createTable(composite); + setControl(composite); + } + + private void createTable(Composite parent) { + Font font = parent.getFont(); + Label map_label = new Label(parent, SWT.WRAP); + map_label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + map_label.setFont(font); + map_label.setText("Files to download during launch:"); //$NON-NLS-1$ + + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(2, false); + layout.marginHeight = 0; + layout.marginWidth = 0; + composite.setFont(font); + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true, 1, 1)); + + viewer = new TableViewer(composite, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.FULL_SELECTION); + Table table = viewer.getTable(); + table.setLayoutData(new GridData(GridData.FILL_BOTH)); + table.setHeaderVisible(true); + table.setLinesVisible(true); + table.setFont(font); + viewer.setContentProvider(new FileListContentProvider()); + viewer.setLabelProvider(new FileListLabelProvider()); + viewer.setColumnProperties(column_ids); + + for (int i = 0; i < column_ids.length; i++) { + TableColumn c = new TableColumn(table, SWT.NONE, i); + c.setText(column_ids[i]); + c.setWidth(column_size[i]); + } + createTableButtons(composite); + viewer.addSelectionChangedListener(new ISelectionChangedListener() { + public void selectionChanged(SelectionChangedEvent event) { + updateLaunchConfigurationDialog(); + } + }); + + viewer.addDoubleClickListener(new IDoubleClickListener() { + @Override + public void doubleClick(DoubleClickEvent event) { + if (button_edit.isEnabled()) { + onEdit((IStructuredSelection)viewer.getSelection()); + } + } + }); + } + + private void createTableButtons(Composite parent) { + Font font = parent.getFont(); + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.marginHeight = 0; + layout.marginWidth = 0; + composite.setFont(font); + composite.setLayout(layout); + GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL); + composite.setLayoutData(gd); + + Menu menu = new Menu(viewer.getTable()); + SelectionAdapter sel_adapter = null; + + button_add = new Button(composite, SWT.PUSH); + button_add.setText(" &Add... "); //$NON-NLS-1$ + gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL); + button_add.setLayoutData(gd); + button_add.addSelectionListener(sel_adapter = new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + Map<String,Object> m = new HashMap<String,Object>(); + DownloadFileDialog dialog = new DownloadFileDialog(getShell(), getPeerID(), m); + if (dialog.open() == Window.OK) { + list.add(m); + viewer.add(m); + viewer.setSelection(new StructuredSelection(m), true); + viewer.getTable().setFocus(); + updateLaunchConfigurationDialog(); + } + } + }); + item_add = new MenuItem(menu, SWT.PUSH); + item_add.setText("&Add..."); //$NON-NLS-1$ + item_add.addSelectionListener(sel_adapter); + item_add.setImage(PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_ADD)); + + button_edit = new Button(composite, SWT.PUSH); + button_edit.setText(" &Edit... "); //$NON-NLS-1$ + button_edit.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + button_edit.addSelectionListener(sel_adapter = new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + onEdit((IStructuredSelection)viewer.getSelection()); + } + }); + item_edit= new MenuItem(menu, SWT.PUSH); + item_edit.setText("&Edit..."); //$NON-NLS-1$ + item_edit.addSelectionListener(sel_adapter); + + button_remove = new Button(composite, SWT.PUSH); + button_remove.setText(" &Remove "); //$NON-NLS-1$ + button_remove.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + button_remove.addSelectionListener(sel_adapter = new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + for (Iterator<?> i = ((IStructuredSelection)viewer.getSelection()).iterator(); i.hasNext();) { + @SuppressWarnings("unchecked") + Map<String,String> m = (Map<String,String>)i.next(); + list.remove(m); + viewer.remove(m); + } + updateLaunchConfigurationDialog(); + } + }); + item_remove = new MenuItem(menu, SWT.PUSH); + item_remove.setText("&Remove"); //$NON-NLS-1$ + item_remove.addSelectionListener(sel_adapter); + item_remove.setImage(PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_ETOOL_DELETE)); + + viewer.getTable().setMenu(menu); + } + + private void onEdit(IStructuredSelection selection) { + @SuppressWarnings("unchecked") + Map<String,Object> m = (Map<String,Object>)selection.getFirstElement(); + DownloadFileDialog dialog = new DownloadFileDialog(getShell(), getPeerID(), m); + dialog.open(); + viewer.refresh(m); + viewer.setSelection(new StructuredSelection(m), true); + viewer.getTable().setFocus(); + updateLaunchConfigurationDialog(); + } + + private String getPeerID() { + String peer_id = "TCP:127.0.0.1:1534"; + for (ILaunchConfigurationTab t : getLaunchConfigurationDialog().getTabs()) { + if (t instanceof TCFTargetTab) peer_id = ((TCFTargetTab)t).getPeerID(); + } + return peer_id; + } + + protected final TableViewer getViewer() { + return viewer; + } + + public void initializeFrom(ILaunchConfiguration config) { + setErrorMessage(null); + setMessage(null); + try { + list.clear(); + final String s = config.getAttribute(TCFLaunchDelegate.ATTR_FILES, ""); //$NON-NLS-1$ + list.addAll(new TCFTask<Collection<Map<String,Object>>>(10000) { + @Override + public void run() { + try { + ArrayList<Map<String,Object>> l = new ArrayList<Map<String,Object>>(); + if (s != null && s.length() > 0) { + @SuppressWarnings("unchecked") + Collection<Map<String,Object>> c = (Collection<Map<String,Object>>)JSON.parseOne(s.getBytes("UTF-8")); + for (Map<String,Object> m : c) l.add(new HashMap<String,Object>(m)); + } + done(l); + } + catch (Throwable e) { + error(e); + } + } + }.get()); + viewer.setInput(config); + button_remove.setEnabled(!viewer.getSelection().isEmpty()); + button_edit.setEnabled(((IStructuredSelection)viewer.getSelection()).size()==1); + item_remove.setEnabled(!viewer.getSelection().isEmpty()); + item_edit.setEnabled(((IStructuredSelection)viewer.getSelection()).size()==1); + } + catch (Exception e) { + init_error = e; + setErrorMessage("Cannot read launch configuration: " + e); //$NON-NLS-1$ + Activator.log(e); + } + } + + public void performApply(ILaunchConfigurationWorkingCopy config) { + if (list.size() == 0) { + config.removeAttribute(TCFLaunchDelegate.ATTR_FILES); + } + else { + String s = new TCFTask<String>(10000) { + @Override + public void run() { + try { + done(JSON.toJSON(list)); + } + catch (Throwable e) { + error(e); + } + } + }.getE(); + config.setAttribute(TCFLaunchDelegate.ATTR_FILES, s); + } + } + + public void setDefaults(ILaunchConfigurationWorkingCopy config) { + config.removeAttribute(TCFLaunchDelegate.ATTR_FILES); + } + + @Override + protected void updateLaunchConfigurationDialog() { + super.updateLaunchConfigurationDialog(); + button_remove.setEnabled(!viewer.getSelection().isEmpty()); + button_edit.setEnabled(((IStructuredSelection)viewer.getSelection()).size() == 1); + item_remove.setEnabled(!viewer.getSelection().isEmpty()); + item_edit.setEnabled(((IStructuredSelection)viewer.getSelection()).size() == 1); + } + + @Override + public boolean isValid(ILaunchConfiguration config) { + setMessage(null); + + if (init_error != null) { + setErrorMessage("Cannot read launch configuration: " + init_error); //$NON-NLS-1$ + return false; + } + + setErrorMessage(null); + return true; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFMainTab.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFMainTab.java index 8952dadd6..803cd369c 100644 --- a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFMainTab.java +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFMainTab.java @@ -66,6 +66,8 @@ public class TCFMainTab extends AbstractLaunchConfigurationTab { comp.setLayout(topLayout); createVerticalSpacer(comp, 1); + createHeader(comp); + createVerticalSpacer(comp, 1); createProjectGroup(comp); createApplicationGroup(comp); createWorkingDirGroup(comp); @@ -73,6 +75,13 @@ public class TCFMainTab extends AbstractLaunchConfigurationTab { createOptionButtons(comp, 1); } + private void createHeader(Composite parent) { + Label label = new Label(parent, SWT.NONE); + label.setText("Launching an application requires a target that supports Processes service"); + GridData gd = new GridData(); + label.setLayoutData(gd); + } + private void createProjectGroup(Composite parent) { Group group = new Group(parent, SWT.NONE); GridLayout layout = new GridLayout(); @@ -493,11 +502,11 @@ public class TCFMainTab extends AbstractLaunchConfigurationTab { } public String getName() { - return "Main"; + return "Application"; } @Override public Image getImage() { - return ImageCache.getImage(ImageCache.IMG_TCF); + return ImageCache.getImage(ImageCache.IMG_APPLICATION_TAB); } } diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFPathMapTab.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFPathMapTab.java index e02b3bcc3..2b35c3817 100644 --- a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFPathMapTab.java +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFPathMapTab.java @@ -310,9 +310,9 @@ public class TCFPathMapTab extends AbstractLaunchConfigurationTab { protected void updateLaunchConfigurationDialog() { super.updateLaunchConfigurationDialog(); button_remove.setEnabled(!viewer.getSelection().isEmpty()); - button_edit.setEnabled(((IStructuredSelection)viewer.getSelection()).size()==1); + button_edit.setEnabled(((IStructuredSelection)viewer.getSelection()).size() == 1); item_remove.setEnabled(!viewer.getSelection().isEmpty()); - item_edit.setEnabled(((IStructuredSelection)viewer.getSelection()).size()==1); + item_edit.setEnabled(((IStructuredSelection)viewer.getSelection()).size() == 1); } @Override diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFTabGroup.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFTabGroup.java index 3d8f8c435..87a1dc941 100644 --- a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFTabGroup.java +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFTabGroup.java @@ -24,8 +24,9 @@ public class TCFTabGroup extends AbstractLaunchConfigurationTabGroup { public void createTabs(ILaunchConfigurationDialog dialog, String mode) { setTabs(new ILaunchConfigurationTab[] { - new TCFMainTab(), new TCFTargetTab(), + new TCFDownloadTab(), + new TCFMainTab(), new TCFArgumentsTab(), new EnvironmentTab(), new TCFMemoryMapTab(), diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFTargetTab.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFTargetTab.java index c8738766f..60ef4b29c 100644 --- a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFTargetTab.java +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFTargetTab.java @@ -13,7 +13,6 @@ package org.eclipse.tcf.internal.debug.ui.launch; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; @@ -29,8 +28,6 @@ import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CLabel; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.TreeEvent; -import org.eclipse.swt.events.TreeListener; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Rectangle; @@ -39,10 +36,8 @@ import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MenuItem; import org.eclipse.swt.widgets.MessageBox; @@ -50,7 +45,6 @@ import org.eclipse.swt.widgets.ProgressBar; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import org.eclipse.swt.widgets.Tree; -import org.eclipse.swt.widgets.TreeColumn; import org.eclipse.swt.widgets.TreeItem; import org.eclipse.tcf.internal.debug.launch.TCFLaunchDelegate; import org.eclipse.tcf.internal.debug.launch.TCFLocalAgent; @@ -58,11 +52,10 @@ import org.eclipse.tcf.internal.debug.launch.TCFUserDefPeer; import org.eclipse.tcf.internal.debug.tests.TCFTestSuite; import org.eclipse.tcf.internal.debug.ui.Activator; import org.eclipse.tcf.internal.debug.ui.ImageCache; +import org.eclipse.tcf.internal.debug.ui.launch.PeerListControl.PeerInfo; import org.eclipse.tcf.internal.debug.ui.launch.setup.SetupWizardDialog; -import org.eclipse.tcf.protocol.IChannel; import org.eclipse.tcf.protocol.IPeer; import org.eclipse.tcf.protocol.Protocol; -import org.eclipse.tcf.services.ILocator; import org.eclipse.tcf.services.IMemoryMap; import org.eclipse.tcf.services.IPathMap; import org.eclipse.tcf.util.TCFTask; @@ -79,129 +72,13 @@ public class TCFTargetTab extends AbstractLaunchConfigurationTab { private Button run_local_agent_button; private Button use_local_agent_button; private Text peer_id_text; + private PeerListControl peer_list; private Tree peer_tree; private Runnable update_peer_buttons; - private final PeerInfo peer_info = new PeerInfo(); private Display display; private Exception init_error; private String mem_map_cfg; - private static class PeerInfo { - PeerInfo parent; - String id; - Map<String,String> attrs; - PeerInfo[] children; - boolean children_pending; - Throwable children_error; - IPeer peer; - IChannel channel; - ILocator locator; - LocatorListener listener; - Runnable item_update; - } - - private class LocatorListener implements ILocator.LocatorListener { - - private final PeerInfo parent; - - LocatorListener(PeerInfo parent) { - this.parent = parent; - } - - public void peerAdded(final IPeer peer) { - if (display == null) return; - final String id = peer.getID(); - final HashMap<String,String> attrs = new HashMap<String,String>(peer.getAttributes()); - display.asyncExec(new Runnable() { - public void run() { - if (parent.children_error != null) return; - PeerInfo[] arr = parent.children; - for (PeerInfo p : arr) assert !p.id.equals(id); - PeerInfo[] buf = new PeerInfo[arr.length + 1]; - System.arraycopy(arr, 0, buf, 0, arr.length); - PeerInfo info = new PeerInfo(); - info.parent = parent; - info.id = id; - info.attrs = attrs; - info.peer = peer; - buf[arr.length] = info; - parent.children = buf; - updateItems(parent); - } - }); - } - - public void peerChanged(final IPeer peer) { - if (display == null) return; - final String id = peer.getID(); - final HashMap<String,String> attrs = new HashMap<String,String>(peer.getAttributes()); - display.asyncExec(new Runnable() { - public void run() { - if (parent.children_error != null) return; - PeerInfo[] arr = parent.children; - for (int i = 0; i < arr.length; i++) { - if (arr[i].id.equals(id)) { - arr[i].attrs = attrs; - arr[i].peer = peer; - updateItems(parent); - } - } - } - }); - } - - public void peerRemoved(final String id) { - if (display == null) return; - display.asyncExec(new Runnable() { - public void run() { - if (parent.children_error != null) return; - PeerInfo[] arr = parent.children; - PeerInfo[] buf = new PeerInfo[arr.length - 1]; - int j = 0; - for (int i = 0; i < arr.length; i++) { - if (arr[i].id.equals(id)) { - final PeerInfo info = arr[i]; - Protocol.invokeLater(new Runnable() { - public void run() { - disconnectPeer(info); - } - }); - } - else { - buf[j++] = arr[i]; - } - } - parent.children = buf; - updateItems(parent); - } - }); - } - - public void peerHeartBeat(final String id) { - if (display == null) return; - display.asyncExec(new Runnable() { - public void run() { - if (parent.children_error != null) return; - PeerInfo[] arr = parent.children; - for (int i = 0; i < arr.length; i++) { - if (arr[i].id.equals(id)) { - if (arr[i].children_error != null) { - TreeItem item = findItem(arr[i]); - boolean visible = item != null; - while (visible && item != null) { - if (!item.getExpanded()) visible = false; - item = item.getParentItem(); - } - if (visible) loadChildren(arr[i]); - } - break; - } - } - } - }); - } - } - public void createControl(Composite parent) { display = parent.getDisplay(); assert display != null; @@ -281,108 +158,18 @@ public class TCFTargetTab extends AbstractLaunchConfigurationTab { peer_label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); peer_label.setFont(font); - loadChildren(peer_info); - createPeerListArea(group); - } - - private void createPeerListArea(Composite parent) { - Font font = parent.getFont(); - Composite composite = new Composite(parent, SWT.NONE); - GridLayout layout = new GridLayout(2, false); - composite.setFont(font); - composite.setLayout(layout); - composite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true, 2, 1)); - - peer_tree = new Tree(composite, SWT.VIRTUAL | SWT.BORDER | SWT.SINGLE); - GridData gd = new GridData(GridData.FILL_BOTH); - gd.minimumHeight = 150; - gd.minimumWidth = 470; - peer_tree.setLayoutData(gd); - - for (int i = 0; i < 6; i++) { - TreeColumn column = new TreeColumn(peer_tree, SWT.LEAD, i); - column.setMoveable(true); - switch (i) { - case 0: - column.setText("Name"); - column.setWidth(160); - break; - case 1: - column.setText("OS"); - column.setWidth(100); - break; - case 2: - column.setText("User"); - column.setWidth(100); - break; - case 3: - column.setText("Transport"); - column.setWidth(60); - break; - case 4: - column.setText("Host"); - column.setWidth(100); - break; - case 5: - column.setText("Port"); - column.setWidth(40); - break; - } - } - - peer_tree.setHeaderVisible(true); - peer_tree.setFont(font); - peer_tree.addListener(SWT.SetData, new Listener() { - public void handleEvent(Event event) { - TreeItem item = (TreeItem)event.item; - PeerInfo info = findPeerInfo(item); - if (info == null) { - updateItems(item.getParentItem(), false); - } - else { - fillItem(item, info); - updateLaunchConfigurationDialog(); - } - } - }); - peer_tree.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetDefaultSelected(SelectionEvent e) { - final PeerInfo info = findPeerInfo(peer_id_text.getText()); - if (info == null) return; - new PeerPropsDialog(getShell(), getImage(), info.attrs, - info.peer instanceof TCFUserDefPeer).open(); - if (!(info.peer instanceof TCFUserDefPeer)) return; - Protocol.invokeLater(new Runnable() { - public void run() { - ((TCFUserDefPeer)info.peer).updateAttributes(info.attrs); - TCFUserDefPeer.savePeers(); - } - }); - } + peer_list = new PeerListControl(group) { @Override - public void widgetSelected(SelectionEvent e) { - TreeItem[] selections = peer_tree.getSelection(); - if (selections.length > 0) { - assert selections.length == 1; - PeerInfo info = findPeerInfo(selections[0]); - if (info != null) peer_id_text.setText(getPath(info)); - } + protected void onPeerListChanged() { updateLaunchConfigurationDialog(); } - }); - peer_tree.addTreeListener(new TreeListener() { - - public void treeCollapsed(TreeEvent e) { - updateItems((TreeItem)e.item, false); - } - - public void treeExpanded(TreeEvent e) { - updateItems((TreeItem)e.item, true); + @Override + protected void onPeerSelected(PeerInfo info) { + peer_id_text.setText(peer_list.getPath(info)); } - }); - - createPeerButtons(composite); + }; + peer_tree = peer_list.getTree(); + createPeerButtons(peer_tree.getParent()); } private void createPeerButtons(Composite parent) { @@ -425,7 +212,7 @@ public class TCFTargetTab extends AbstractLaunchConfigurationTab { button_edit.addSelectionListener(sel_adapter = new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { - final PeerInfo info = findPeerInfo(peer_id_text.getText()); + final PeerInfo info = peer_list.findPeerInfo(peer_id_text.getText()); if (info == null) return; if (new PeerPropsDialog(getShell(), getImage(), info.attrs, info.peer instanceof TCFUserDefPeer).open() != Window.OK) return; @@ -448,7 +235,7 @@ public class TCFTargetTab extends AbstractLaunchConfigurationTab { button_remove.addSelectionListener(sel_adapter = new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { - final PeerInfo info = findPeerInfo(peer_id_text.getText()); + final PeerInfo info = peer_list.findPeerInfo(peer_id_text.getText()); if (info == null) return; if (!(info.peer instanceof TCFUserDefPeer)) return; peer_id_text.setText(""); @@ -500,7 +287,7 @@ public class TCFTargetTab extends AbstractLaunchConfigurationTab { public void run() { boolean local = use_local_agent_button.getSelection(); - PeerInfo info = findPeerInfo(peer_id_text.getText()); + PeerInfo info = peer_list.findPeerInfo(peer_id_text.getText()); button_new.setEnabled(!local); button_edit.setEnabled(info != null && !local); button_remove.setEnabled(info != null && info.peer instanceof TCFUserDefPeer && !local); @@ -530,7 +317,7 @@ public class TCFTargetTab extends AbstractLaunchConfigurationTab { peer_tree.setEnabled(true); peer_id_text.setEnabled(true); String id = peer_id_text.getText(); - TreeItem item = findItem(id); + TreeItem item = peer_list.findItem(id); if (item != null) peer_tree.setSelection(item); else peer_tree.deselectAll(); } @@ -538,17 +325,6 @@ public class TCFTargetTab extends AbstractLaunchConfigurationTab { super.updateLaunchConfigurationDialog(); } - @Override - public void dispose() { - Protocol.invokeAndWait(new Runnable() { - public void run() { - disconnectPeer(peer_info); - display = null; - } - }); - super.dispose(); - } - public String getName() { return "Target"; } @@ -568,9 +344,8 @@ public class TCFTargetTab extends AbstractLaunchConfigurationTab { setMessage(null); try { String id = configuration.getAttribute(TCFLaunchDelegate.ATTR_PEER_ID, ""); - TreeItem item = findItem(id); - if (item != null) peer_tree.setSelection(item); peer_id_text.setText(id); + peer_list.setInitialSelection(id); run_local_agent_button.setSelection(configuration.getAttribute(TCFLaunchDelegate.ATTR_RUN_LOCAL_AGENT, false)); use_local_agent_button.setSelection(configuration.getAttribute(TCFLaunchDelegate.ATTR_USE_LOCAL_AGENT, true)); mem_map_cfg = configuration.getAttribute(TCFLaunchDelegate.ATTR_MEMORY_MAP, "null"); @@ -613,324 +388,8 @@ public class TCFTargetTab extends AbstractLaunchConfigurationTab { return true; } - private void disconnectPeer(final PeerInfo info) { - assert Protocol.isDispatchThread(); - if (info.children != null) { - for (PeerInfo p : info.children) disconnectPeer(p); - } - if (info.listener != null) { - info.locator.removeListener(info.listener); - info.listener = null; - info.locator = null; - } - if (info.channel != null) { - info.channel.close(); - } - } - - private boolean canHaveChildren(PeerInfo parent) { - return parent == peer_info || parent.attrs.get(IPeer.ATTR_PROXY) != null; - } - - private void loadChildren(final PeerInfo parent) { - assert Thread.currentThread() == display.getThread(); - if (parent.children_pending) return; - assert parent.children == null; - parent.children_pending = true; - parent.children_error = null; - Protocol.invokeAndWait(new Runnable() { - public void run() { - assert parent.listener == null; - assert parent.channel == null; - if (!canHaveChildren(parent)) { - doneLoadChildren(parent, null, new PeerInfo[0]); - } - else if (parent == peer_info) { - peer_info.locator = Protocol.getLocator(); - doneLoadChildren(parent, null, createLocatorListener(peer_info)); - } - else { - final IChannel channel = parent.peer.openChannel(); - parent.channel = channel; - parent.channel.addChannelListener(new IChannel.IChannelListener() { - boolean opened = false; - boolean closed = false; - public void congestionLevel(int level) { - } - public void onChannelClosed(final Throwable error) { - assert !closed; - if (parent.channel != channel) return; - if (!opened) { - doneLoadChildren(parent, error, null); - } - else { - if (display != null) { - display.asyncExec(new Runnable() { - public void run() { - if (parent.children_pending) return; - parent.children = null; - parent.children_error = error; - updateItems(parent); - } - }); - } - } - closed = true; - parent.channel = null; - parent.locator = null; - parent.listener = null; - } - public void onChannelOpened() { - assert !opened; - assert !closed; - if (parent.channel != channel) return; - opened = true; - parent.locator = parent.channel.getRemoteService(ILocator.class); - if (parent.locator == null) { - parent.channel.terminate(new Exception("Service not supported: " + ILocator.NAME)); - } - else { - doneLoadChildren(parent, null, createLocatorListener(parent)); - } - } - }); - } - } - }); - } - - private PeerInfo[] createLocatorListener(PeerInfo peer) { - assert Protocol.isDispatchThread(); - Map<String,IPeer> map = peer.locator.getPeers(); - PeerInfo[] buf = new PeerInfo[map.size()]; - int n = 0; - for (IPeer p : map.values()) { - PeerInfo info = new PeerInfo(); - info.parent = peer; - info.id = p.getID(); - info.attrs = new HashMap<String,String>(p.getAttributes()); - info.peer = p; - buf[n++] = info; - } - peer.listener = new LocatorListener(peer); - peer.locator.addListener(peer.listener); - return buf; - } - - private void doneLoadChildren(final PeerInfo parent, final Throwable error, final PeerInfo[] children) { - assert Protocol.isDispatchThread(); - assert error == null || children == null; - if (display == null) return; - display.asyncExec(new Runnable() { - public void run() { - assert parent.children_pending; - assert parent.children == null; - parent.children_pending = false; - parent.children = children; - parent.children_error = error; - updateItems(parent); - } - }); - } - - private ArrayList<PeerInfo> filterPeerList(PeerInfo parent, boolean expanded) { - ArrayList<PeerInfo> lst = new ArrayList<PeerInfo>(); - HashMap<String,PeerInfo> local_agents = new HashMap<String,PeerInfo>(); - HashSet<String> ids = new HashSet<String>(); - for (PeerInfo p : parent.children) { - String id = p.attrs.get(IPeer.ATTR_AGENT_ID); - if (id == null) continue; - if (!"TCP".equals(p.attrs.get(IPeer.ATTR_TRANSPORT_NAME))) continue; - if (!"127.0.0.1".equals(p.attrs.get(IPeer.ATTR_IP_HOST))) continue; - local_agents.put(id, p); - ids.add(p.id); - } - for (PeerInfo p : parent.children) { - PeerInfo i = local_agents.get(p.attrs.get(IPeer.ATTR_AGENT_ID)); - if (i != null && i != p) continue; - lst.add(p); - } - if (parent != peer_info && expanded) { - for (PeerInfo p : peer_info.children) { - if (p.peer instanceof TCFUserDefPeer && !ids.contains(p.id)) { - PeerInfo x = new PeerInfo(); - x.parent = parent; - x.id = p.id; - x.attrs = p.attrs; - x.peer = p.peer; - ids.add(x.id); - lst.add(x); - } - } - } - return lst; - } - - private void updateItems(TreeItem parent_item, boolean reload) { - final PeerInfo parent_info = findPeerInfo(parent_item); - if (parent_info == null) { - parent_item.setText("Invalid"); - } - else { - if (reload && parent_info.children_error != null) { - loadChildren(parent_info); - } - display.asyncExec(new Runnable() { - public void run() { - updateItems(parent_info); - } - }); - } - } - - private void updateItems(final PeerInfo parent) { - if (display == null) return; - assert Thread.currentThread() == display.getThread(); - parent.item_update = new Runnable() { - public void run() { - if (display == null) return; - if (parent.item_update != this) return; - if (Thread.currentThread() != display.getThread()) { - display.asyncExec(this); - return; - } - parent.item_update = null; - TreeItem[] items = null; - boolean expanded = true; - if (parent.children == null || parent.children_error != null) { - if (parent == peer_info) { - peer_tree.setItemCount(1); - items = peer_tree.getItems(); - } - else { - TreeItem item = findItem(parent); - if (item == null) return; - expanded = item.getExpanded(); - item.setItemCount(1); - items = item.getItems(); - } - assert items.length == 1; - if (parent.children_pending) { - items[0].setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND)); - fillItem(items[0], "Connecting..."); - } - else if (parent.children_error != null) { - String msg = parent.children_error.getMessage(); - if (msg == null) msg = parent.children_error.getClass().getName(); - else msg = msg.replace('\n', ' '); - items[0].setForeground(display.getSystemColor(SWT.COLOR_RED)); - fillItem(items[0], msg); - } - else if (expanded) { - loadChildren(parent); - items[0].setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND)); - fillItem(items[0], "Connecting..."); - } - else { - Protocol.invokeAndWait(new Runnable() { - public void run() { - disconnectPeer(parent); - } - }); - fillItem(items[0], ""); - } - } - else { - ArrayList<PeerInfo> lst = null; - if (parent == peer_info) { - lst = filterPeerList(parent, expanded); - peer_tree.setItemCount(lst.size() > 0 ? lst.size() : 1); - items = peer_tree.getItems(); - } - else { - TreeItem item = findItem(parent); - if (item == null) return; - expanded = item.getExpanded(); - lst = filterPeerList(parent, expanded); - item.setItemCount(expanded && lst.size() > 0 ? lst.size() : 1); - items = item.getItems(); - } - if (expanded && lst.size() > 0) { - assert items.length == lst.size(); - for (int i = 0; i < items.length; i++) fillItem(items[i], lst.get(i)); - } - else if (expanded) { - fillItem(items[0], "No peers"); - } - else { - Protocol.invokeAndWait(new Runnable() { - public void run() { - disconnectPeer(parent); - } - }); - fillItem(items[0], ""); - } - } - updateLaunchConfigurationDialog(); - } - }; - if (parent.children_pending) parent.item_update.run(); - else Protocol.invokeLater(200, parent.item_update); - } - - private TreeItem findItem(String path) { - assert Thread.currentThread() == display.getThread(); - if (path == null) return null; - int z = path.lastIndexOf('/'); - if (z < 0) { - int n = peer_tree.getItemCount(); - for (int i = 0; i < n; i++) { - TreeItem x = peer_tree.getItem(i); - PeerInfo p = (PeerInfo)x.getData("TCFPeerInfo"); - if (p != null && p.id.equals(path)) return x; - } - } - else { - TreeItem y = findItem(path.substring(0, z)); - if (y == null) return null; - String id = path.substring(z + 1); - int n = y.getItemCount(); - for (int i = 0; i < n; i++) { - TreeItem x = y.getItem(i); - PeerInfo p = (PeerInfo)x.getData("TCFPeerInfo"); - if (p != null && p.id.equals(id)) return x; - } - } - return null; - } - - private TreeItem findItem(PeerInfo info) { - if (info == null) return null; - assert info.parent != null; - if (info.parent == peer_info) { - int n = peer_tree.getItemCount(); - for (int i = 0; i < n; i++) { - TreeItem x = peer_tree.getItem(i); - if (x.getData("TCFPeerInfo") == info) return x; - } - } - else { - TreeItem y = findItem(info.parent); - if (y == null) return null; - int n = y.getItemCount(); - for (int i = 0; i < n; i++) { - TreeItem x = y.getItem(i); - if (x.getData("TCFPeerInfo") == info) return x; - } - } - return null; - } - - private PeerInfo findPeerInfo(String path) { - TreeItem i = findItem(path); - if (i == null) return null; - return (PeerInfo)i.getData("TCFPeerInfo"); - } - - private PeerInfo findPeerInfo(TreeItem item) { - assert Thread.currentThread() == display.getThread(); - if (item == null) return peer_info; - return (PeerInfo)item.getData("TCFPeerInfo"); + public String getPeerID() { + return peer_id_text.getText(); } private void runDiagnostics(boolean loop) { @@ -955,7 +414,7 @@ public class TCFTargetTab extends AbstractLaunchConfigurationTab { } } else { - PeerInfo info = findPeerInfo(peer_id_text.getText()); + PeerInfo info = peer_list.findPeerInfo(peer_id_text.getText()); if (info == null) return; peer = info.peer; } @@ -1066,46 +525,4 @@ public class TCFTargetTab extends AbstractLaunchConfigurationTab { } }); } - - private void fillItem(TreeItem item, PeerInfo info) { - assert Thread.currentThread() == display.getThread(); - Object data = item.getData("TCFPeerInfo"); - if (data != null && data != info) item.removeAll(); - item.setData("TCFPeerInfo", info); - String text[] = new String[6]; - text[0] = info.attrs.get(IPeer.ATTR_NAME); - text[1] = info.attrs.get(IPeer.ATTR_OS_NAME); - text[2] = info.attrs.get(IPeer.ATTR_USER_NAME); - text[3] = info.attrs.get(IPeer.ATTR_TRANSPORT_NAME); - text[4] = info.attrs.get(IPeer.ATTR_IP_HOST); - text[5] = info.attrs.get(IPeer.ATTR_IP_PORT); - for (int i = 0; i < text.length; i++) { - if (text[i] == null) text[i] = ""; - } - item.setText(text); - item.setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND)); - item.setImage(ImageCache.getImage(getImageName(info))); - if (!canHaveChildren(info)) item.setItemCount(0); - else if (info.children == null || info.children_error != null) item.setItemCount(1); - else item.setItemCount(info.children.length); - } - - private void fillItem(TreeItem item, String text) { - item.setText(text); - item.setData("TCFPeerInfo", null); - int n = peer_tree.getColumnCount(); - for (int i = 1; i < n; i++) item.setText(i, ""); - item.setImage((Image)null); - item.removeAll(); - } - - private String getPath(PeerInfo info) { - if (info == peer_info) return ""; - if (info.parent == peer_info) return info.id; - return getPath(info.parent) + "/" + info.id; - } - - private String getImageName(PeerInfo info) { - return ImageCache.IMG_TARGET_TAB; - } } diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModel.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModel.java index 056f21049..b2274c526 100644 --- a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModel.java +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModel.java @@ -10,6 +10,7 @@ *******************************************************************************/ package org.eclipse.tcf.internal.debug.ui.model; +import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -1962,6 +1963,9 @@ public class TCFModel implements ITCFModel, IElementContentProvider, IElementLab if (!multiline && error instanceof IErrorReport) { msg = Command.toErrorString(((IErrorReport)error).getAttributes()); } + else if (error instanceof UnknownHostException) { + msg = "Unknown host: " + error.getMessage(); + } else { msg = error.getLocalizedMessage(); } @@ -1976,8 +1980,8 @@ public class TCFModel implements ITCFModel, IElementContentProvider, IElementLab else if (ch != '.' && ch != ';') { buf.append(';'); } - buf.append("Caused by:"); - buf.append(multiline ? '\n' : ' '); + if (multiline) buf.append("Caused by:\n"); + else buf.append(' '); } } if (buf.length() > 0) { diff --git a/plugins/org.eclipse.tcf.debug/src/org/eclipse/tcf/internal/debug/launch/TCFLaunchDelegate.java b/plugins/org.eclipse.tcf.debug/src/org/eclipse/tcf/internal/debug/launch/TCFLaunchDelegate.java index e58b05355..edac36a91 100644 --- a/plugins/org.eclipse.tcf.debug/src/org/eclipse/tcf/internal/debug/launch/TCFLaunchDelegate.java +++ b/plugins/org.eclipse.tcf.debug/src/org/eclipse/tcf/internal/debug/launch/TCFLaunchDelegate.java @@ -62,8 +62,23 @@ public class TCFLaunchDelegate extends LaunchConfigurationDelegate { ATTR_USE_LOCAL_AGENT = ITCFConstants.ID_TCF_DEBUG_MODEL + ".UseLocalAgent", ATTR_SIGNALS_DONT_STOP = ITCFConstants.ID_TCF_DEBUG_MODEL + ".SignalsDontStop", ATTR_SIGNALS_DONT_PASS = ITCFConstants.ID_TCF_DEBUG_MODEL + ".SignalsDontPath", + ATTR_FILES = ITCFConstants.ID_TCF_DEBUG_MODEL + ".Files", ATTR_PATH_MAP = ITCFConstants.ID_TCF_DEBUG_MODEL + ".PathMap", - ATTR_MEMORY_MAP = ITCFConstants.ID_TCF_DEBUG_MODEL + ".MemoryMap"; + ATTR_MEMORY_MAP = ITCFConstants.ID_TCF_DEBUG_MODEL + ".MemoryMap", + ATTR_ATTACH_PATH = ITCFConstants.ID_TCF_DEBUG_MODEL + ".Attach"; + + public static final String + FILES_CONTEXT_FULL_NAME = "Context", + FILES_CONTEXT_ID = "ContextID", + FILES_FILE_NAME = "File", + FILES_LOAD_SYMBOLS = "LoadSymbols", + FILES_RELOCATE = "Relocate", + FILES_ADDRESS = IMemoryMap.PROP_ADDRESS, + FILES_OFFSET = IMemoryMap.PROP_OFFSET, + FILES_SIZE = IMemoryMap.PROP_SIZE, + FILES_DOWNLOAD = "Download", + FILES_SET_PC = "SetPC", + FILES_ENABLE_OSA = "EnableOSA"; public static class PathMapRule extends TCFPathMapRule { diff --git a/plugins/org.eclipse.tcf.debug/src/org/eclipse/tcf/internal/debug/model/ElfLoader.java b/plugins/org.eclipse.tcf.debug/src/org/eclipse/tcf/internal/debug/model/ElfLoader.java new file mode 100644 index 000000000..043682617 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug/src/org/eclipse/tcf/internal/debug/model/ElfLoader.java @@ -0,0 +1,470 @@ +/******************************************************************************* + * Copyright (c) 2013 Xilinx, 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: + * Xilinx - initial API and implementation + *******************************************************************************/ +package org.eclipse.tcf.internal.debug.model; + +import java.io.File; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.tcf.internal.debug.launch.TCFLaunchDelegate; +import org.eclipse.tcf.protocol.IChannel; +import org.eclipse.tcf.protocol.IToken; +import org.eclipse.tcf.protocol.Protocol; +import org.eclipse.tcf.services.IMemory; +import org.eclipse.tcf.services.IRegisters; +import org.eclipse.tcf.services.IRegisters.RegistersContext; +import org.eclipse.tcf.services.IRunControl; + +public class ElfLoader implements Runnable { + + private final IChannel channel; + + /* Loader parameters */ + private Map<String,Object> args; + private boolean download; + private boolean set_pc; + private Runnable done; + + /* Services */ + private final IRunControl service_rc; + private final IMemory service_mem; + private final IRegisters service_regs; + + /* Pending commands */ + private final Set<IToken> cmds = new HashSet<IToken>(); + + /* Debug contexts */ + private final Map<String,IRunControl.RunControlContext> contexts = + new HashMap<String,IRunControl.RunControlContext>(); + + /* Running debug contexts */ + private final Set<String> running = new HashSet<String>(); + + private List<Throwable> errors = new ArrayList<Throwable>(); + + private final IRunControl.RunControlListener rc_listener= new IRunControl.RunControlListener() { + @Override + public void contextSuspended(String id, String pc, String reason, Map<String, Object> params) { + running.remove(id); + run(); + } + @Override + public void contextResumed(String id) { + running.add(id); + run(); + } + @Override + public void contextRemoved(String[] context_ids) { + for (String id : context_ids) { + contexts.remove(id); + running.remove(id); + } + run(); + } + @Override + public void contextException(String context, String msg) { + } + @Override + public void contextChanged(IRunControl.RunControlContext[] contexts) { + } + @Override + public void contextAdded(IRunControl.RunControlContext[] arr) { + for (IRunControl.RunControlContext ctx : arr) { + String id = ctx.getID(); + contexts.put(id, ctx); + if (ctx.hasState()) running.add(id); + } + run(); + } + @Override + public void containerSuspended(String context, String pc, String reason, + Map<String, Object> params, String[] suspended_ids) { + for (String id : suspended_ids) running.remove(id); + run(); + } + @Override + public void containerResumed(String[] context_ids) { + for (String id : context_ids) running.add(id); + run(); + } + }; + + private final IRunControl.DoneGetContext done_ctx_get_context = new IRunControl.DoneGetContext() { + @Override + public void doneGetContext(IToken token, Exception error, final IRunControl.RunControlContext context) { + cmds.remove(token); + if (error != null) { + errors.add(error); + } + else { + final String id = context.getID(); + contexts.put(id, context); + if (context.hasState()) { + cmds.add(context.getState(new IRunControl.DoneGetState() { + @Override + public void doneGetState(IToken token, Exception error, + boolean suspended, String pc, String reason, Map<String, Object> params) { + cmds.remove(token); + if (error != null) { + errors.add(error); + } + else if (!suspended) { + running.add(id); + } + run(); + } + })); + } + } + run(); + } + }; + + private final IRunControl.DoneGetChildren done_ctx_get_children = new IRunControl.DoneGetChildren() { + @Override + public void doneGetChildren(IToken token, Exception error, String[] context_ids) { + cmds.remove(token); + if (error != null) { + errors.add(error); + } + else if (context_ids != null) { + for (String id : context_ids) { + cmds.add(service_rc.getContext(id, done_ctx_get_context)); + cmds.add(service_rc.getChildren(id, this)); + } + } + run(); + } + }; + + private final IMemory.DoneGetContext done_mem_get_context = new IMemory.DoneGetContext() { + @Override + public void doneGetContext(IToken token, Exception error, IMemory.MemoryContext context) { + cmds.remove(token); + if (error != null) { + errors.add(error); + } + else { + assert context != null; + mem_ctx = context; + File fnm = null; + try { + fnm = new File((String)args.get(TCFLaunchDelegate.FILES_FILE_NAME)); + file = new RandomAccessFile(fnm, "r"); + try { + downloadFile(context); + } + finally { + file.close(); + } + } + catch (Exception e) { + if (fnm != null) e = new Exception("Cannot read '" + fnm.getName() + "'", e); + errors.add(e); + } + file = null; + } + run(); + } + }; + + private final IRegisters.DoneGetChildren done_regs_get_children = new IRegisters.DoneGetChildren() { + @Override + public void doneGetChildren(IToken token, Exception error, String[] context_ids) { + cmds.remove(token); + if (error != null) errors.add(error); + if (context_ids != null) { + for (String id : context_ids) { + cmds.add(service_regs.getContext(id, new IRegisters.DoneGetContext() { + @Override + public void doneGetContext(IToken token, Exception error, RegistersContext context) { + cmds.remove(token); + if (error != null) errors.add(error); + if (context != null) { + if (IRegisters.ROLE_PC.equals(context.getRole())) { + reg_pc = context; + setEntryAddress(); + } + else if (reg_pc == null && errors.size() == 0) { + cmds.add(service_regs.getChildren(context.getID(), done_regs_get_children)); + } + } + run(); + } + })); + } + } + run(); + } + }; + + private static final int PT_LOAD = 1; + + private boolean listener_ok; + private boolean started_context_retrieval; + private boolean started_reginfo_retrieval; + private boolean disposed; + + private RandomAccessFile file; + private boolean big_endian; + private boolean elf64; + private IMemory.MemoryContext mem_ctx; + private BigInteger entry_addr; + private RegistersContext reg_pc; + private long start_time; + + ElfLoader(IChannel channel) { + this.channel = channel; + service_rc = channel.getRemoteService(IRunControl.class); + service_mem = channel.getRemoteService(IMemory.class); + service_regs = channel.getRemoteService(IRegisters.class); + } + + void load(Map<String,Object> args, Runnable done) { + this.args = args; + this.done = done; + Boolean b1 = (Boolean)args.get(TCFLaunchDelegate.FILES_DOWNLOAD); + Boolean b2 = (Boolean)args.get(TCFLaunchDelegate.FILES_SET_PC); + download = b1 != null && b1.booleanValue(); + set_pc = b2 != null && b2.booleanValue(); + start_time = System.currentTimeMillis(); + started_reginfo_retrieval = false; + entry_addr = null; + mem_ctx = null; + reg_pc = null; + Protocol.invokeLater(this); + } + + void dispose() { + if (service_rc != null) service_rc.removeListener(rc_listener); + disposed = true; + } + + private BigInteger readNumberX() throws IOException { + int size = elf64 ? 8 : 4; + byte[] buf = new byte[size + 1]; + file.readFully(buf, 1, size); + if (!big_endian) { + for (int i = 0; i < size / 2; i++) { + byte x = buf[i + 1]; + buf[i + 1] = buf[size - i]; + buf[size - i] = x; + } + } + return new BigInteger(buf); + } + + private int readInt2() throws IOException { + int x = file.readUnsignedByte(); + int y = file.readUnsignedByte(); + return big_endian ? (x << 8) + y : x + (y << 8); + } + + private int readInt4() throws IOException { + int x = readInt2(); + int y = readInt2(); + return big_endian ? (x << 16) + y : x + (y << 16); + } + + private void downloadFile(IMemory.MemoryContext context) throws Exception { + if (file.readByte() != 0x7f || file.readByte() != 'E' || + file.readByte() != 'L' || file.readByte() != 'F') + throw new IOException("Not an ELF file"); + switch (file.readByte()) { + case 1: + elf64 = false; + break; + case 2: + elf64 = true; + break; + default: + throw new IOException("Invalid ELF file"); + } + switch (file.readByte()) { + case 1: + big_endian = false; + break; + case 2: + big_endian = true; + break; + default: + throw new IOException("Invalid ELF file"); + } + + file.seek(24); + + entry_addr = readNumberX(); + if (download) { + BigInteger phoff = readNumberX(); + @SuppressWarnings("unused") + BigInteger shoff = readNumberX(); + file.skipBytes(6); + int phentsize = readInt2(); + int phnum = readInt2(); + + for (int n = 0; n < phnum; n++) { + file.seek(phoff.longValue() + n * phentsize); + int p_type = readInt4(); + if (p_type != PT_LOAD) continue; + if (elf64) readInt4(); + BigInteger p_offset = readNumberX(); + BigInteger p_vaddr = readNumberX(); + @SuppressWarnings("unused") + BigInteger p_paddr = readNumberX(); + BigInteger p_filesz = readNumberX(); + BigInteger p_memsz = readNumberX(); + byte buf[] = new byte[p_filesz.intValue()]; + file.seek(p_offset.longValue()); + file.readFully(buf); + cmds.add(context.set(p_vaddr, 4, buf, 0, buf.length, 0, new IMemory.DoneMemory() { + @Override + public void doneMemory(IToken token, IMemory.MemoryError error) { + cmds.remove(token); + if (error != null) errors.add(error); + run(); + } + })); + BigInteger fill = p_memsz.subtract(p_filesz); + if (fill.compareTo(BigInteger.ZERO) > 0) { + buf = new byte[4]; + cmds.add(context.fill(p_vaddr.add(p_filesz), 4, buf, fill.intValue(), 0, new IMemory.DoneMemory() { + @Override + public void doneMemory(IToken token, IMemory.MemoryError error) { + cmds.remove(token); + if (error != null) errors.add(error); + run(); + } + })); + } + } + } + } + + private void setEntryAddress() { + byte[] value = new byte[reg_pc.getSize()]; + boolean big_endian = reg_pc.isBigEndian(); + + BigInteger n = entry_addr; + for (int i = 0; i < value.length; i++) { + value[big_endian ? value.length - i - 1 : i] = n.byteValue(); + n = n.shiftRight(8); + } + + cmds.add(reg_pc.set(value, new IRegisters.DoneSet() { + @Override + public void doneSet(IToken token, Exception error) { + cmds.remove(token); + if (error != null) errors.add(error); + run(); + } + })); + } + + private String getFullName(IRunControl.RunControlContext ctx) { + if (ctx == null) return null; + String name = ctx.getName(); + if (name == null) name = ctx.getID(); + String parent = ctx.getParentID(); + if (parent == null) return "/" + name; + String path = getFullName(contexts.get(parent)); + if (path == null) return null; + return path + '/' + name; + } + + public void run() { + /* Wait for pending commands */ + if (cmds.size() > 0) return; + + if (disposed) return; + if (done == null) return; + + if (service_rc == null || service_mem == null) { + errors.add(new Error("No services, cannot do anything")); + } + + if (!listener_ok) { + service_rc.addListener(rc_listener); + listener_ok = true; + } + + if (errors.size() == 0 && !started_context_retrieval) { + /* Retrieve debug context information */ + cmds.add(service_rc.getChildren(null, done_ctx_get_children)); + started_context_retrieval = true; + return; + } + + /* Suspend everything */ + if (errors.size() == 0 && running.size() > 0) { + if (System.currentTimeMillis() - start_time < 5000) { + for (final String id : running) { + IRunControl.RunControlContext ctx = contexts.get(id); + if (ctx != null) { + cmds.add(ctx.suspend(new IRunControl.DoneCommand() { + @Override + public void doneCommand(IToken token, Exception error) { + cmds.remove(token); + if (error != null && running.contains(id)) errors.add(error); + run(); + } + })); + } + } + if (cmds.size() > 0) return; + } + errors.add(new Exception("Cannot stop the target")); + } + + if (errors.size() == 0 && mem_ctx == null) { + /* Download the file */ + String id = (String)args.get(TCFLaunchDelegate.FILES_CONTEXT_ID); + if (id != null) { + cmds.add(service_mem.getContext(id, done_mem_get_context)); + return; + } + String name = (String)args.get(TCFLaunchDelegate.FILES_CONTEXT_FULL_NAME); + if (name != null) { + for (IRunControl.RunControlContext ctx : contexts.values()) { + if (name.equals(getFullName(ctx))) { + cmds.add(service_mem.getContext(ctx.getID(), done_mem_get_context)); + } + } + if (cmds.size() > 0) return; + } + /* Wait for context */ + if (System.currentTimeMillis() - start_time < 5000) { + Protocol.invokeLater(200, this); + return; + } + errors.add(new Exception( + "Context not found: " + + (name != null ? name : id))); + } + + if (errors.size() == 0 && mem_ctx != null && entry_addr != null && + set_pc && !started_reginfo_retrieval && service_regs != null) { + started_reginfo_retrieval = true; + cmds.add(service_regs.getChildren(mem_ctx.getID(), done_regs_get_children)); + return; + } + /* All done */ + if (errors.size() > 0) channel.terminate(new Exception("Download error", errors.get(0))); + Protocol.invokeLater(done); + done = null; + } +} diff --git a/plugins/org.eclipse.tcf.debug/src/org/eclipse/tcf/internal/debug/model/TCFLaunch.java b/plugins/org.eclipse.tcf.debug/src/org/eclipse/tcf/internal/debug/model/TCFLaunch.java index b926b9889..5535096a9 100644 --- a/plugins/org.eclipse.tcf.debug/src/org/eclipse/tcf/internal/debug/model/TCFLaunch.java +++ b/plugins/org.eclipse.tcf.debug/src/org/eclipse/tcf/internal/debug/model/TCFLaunch.java @@ -40,6 +40,7 @@ import org.eclipse.tcf.protocol.IChannel; import org.eclipse.tcf.protocol.IPeer; import org.eclipse.tcf.protocol.IService; import org.eclipse.tcf.protocol.IToken; +import org.eclipse.tcf.protocol.JSON; import org.eclipse.tcf.protocol.Protocol; import org.eclipse.tcf.services.IContextQuery; import org.eclipse.tcf.services.IFileSystem; @@ -412,6 +413,34 @@ public class TCFLaunch extends Launch { } } + if (cfg != null && getService(IMemory.class) != null) { + String s = cfg.getAttribute(TCFLaunchDelegate.ATTR_FILES, (String)null); + if (s != null) { + @SuppressWarnings("unchecked") + Collection<Map<String,Object>> c = (Collection<Map<String,Object>>)JSON.parseOne(s.getBytes("UTF-8")); + final ElfLoader loader = new ElfLoader(channel); + for (final Map<String,Object> m : c) { + Boolean b1 = (Boolean)m.get(TCFLaunchDelegate.FILES_DOWNLOAD); + Boolean b2 = (Boolean)m.get(TCFLaunchDelegate.FILES_SET_PC); + if (b1 != null && b1.booleanValue() || b2 != null && b2.booleanValue()) { + new LaunchStep() { + @Override + void start() throws Exception { + loader.load(m, this); + } + }; + } + } + new LaunchStep() { + @Override + void start() throws Exception { + loader.dispose(); + done(); + } + }; + } + } + // Call client launch sequence: new LaunchStep() { @Override @@ -478,7 +507,7 @@ public class TCFLaunch extends Launch { return; } final HashMap<String,ArrayList<IMemoryMap.MemoryRegion>> maps = new HashMap<String,ArrayList<IMemoryMap.MemoryRegion>>(); - TCFLaunchDelegate.getMemMapsAttribute(maps, cfg); + getMemMaps(maps, cfg); final HashSet<IToken> cmds = new HashSet<IToken>(); // Pending commands final Runnable done_all = new Runnable() { boolean launch_done; @@ -506,7 +535,7 @@ public class TCFLaunch extends Launch { try { Set<String> set = new HashSet<String>(maps.keySet()); maps.clear(); - TCFLaunchDelegate.getMemMapsAttribute(maps, getLaunchConfiguration()); + getMemMaps(maps, getLaunchConfiguration()); for (String id : maps.keySet()) { ArrayList<IMemoryMap.MemoryRegion> map = maps.get(id); TCFMemoryRegion[] arr = map.toArray(new TCFMemoryRegion[map.size()]); @@ -534,7 +563,7 @@ public class TCFLaunch extends Launch { } final HashSet<String> deleted_maps = new HashSet<String>(); final HashMap<String,ArrayList<IMemoryMap.MemoryRegion>> maps = new HashMap<String,ArrayList<IMemoryMap.MemoryRegion>>(); - TCFLaunchDelegate.getMemMapsAttribute(maps, cfg); + getMemMaps(maps, cfg); final HashSet<String> mems = new HashSet<String>(); // Already processed memory IDs final HashSet<IToken> cmds = new HashSet<IToken>(); // Pending commands final HashMap<String,String> mem2map = new HashMap<String,String>(); @@ -631,7 +660,7 @@ public class TCFLaunch extends Launch { try { maps.clear(); mems.clear(); - TCFLaunchDelegate.getMemMapsAttribute(maps, getLaunchConfiguration()); + getMemMaps(maps, getLaunchConfiguration()); for (String id : mem2map.values()) { if (maps.get(id) == null) deleted_maps.add(id); } @@ -644,6 +673,40 @@ public class TCFLaunch extends Launch { }; } + @SuppressWarnings("unchecked") + private void getMemMaps(Map<String,ArrayList<IMemoryMap.MemoryRegion>> maps, ILaunchConfiguration cfg) throws Exception { + // Parse ATTR_FILES + String s = cfg.getAttribute(TCFLaunchDelegate.ATTR_FILES, (String)null); + if (s != null) { + Collection<Map<String,Object>> c = (Collection<Map<String,Object>>)JSON.parseOne(s.getBytes("UTF-8")); + for (Map<String,Object> m : c) { + Boolean b = (Boolean)m.get(TCFLaunchDelegate.FILES_LOAD_SYMBOLS); + if (b != null && b.booleanValue()) { + String id = (String)m.get(TCFLaunchDelegate.FILES_CONTEXT_ID); + if (id == null) id = (String)m.get(TCFLaunchDelegate.FILES_CONTEXT_FULL_NAME); + if (id != null) { + Map<String,Object> map = new HashMap<String,Object>(); + map.put(IMemoryMap.PROP_FILE_NAME, m.get(TCFLaunchDelegate.FILES_FILE_NAME)); + b = (Boolean)m.get(TCFLaunchDelegate.FILES_RELOCATE); + if (b != null && b.booleanValue()) { + map.put(IMemoryMap.PROP_ADDRESS, m.get(TCFLaunchDelegate.FILES_ADDRESS)); + map.put(IMemoryMap.PROP_OFFSET, m.get(TCFLaunchDelegate.FILES_OFFSET)); + map.put(IMemoryMap.PROP_SIZE, m.get(TCFLaunchDelegate.FILES_SIZE)); + } + ArrayList<IMemoryMap.MemoryRegion> l = maps.get(id); + if (l == null) { + l = new ArrayList<IMemoryMap.MemoryRegion>(); + maps.put(id, l); + } + l.add(new TCFMemoryRegion(map)); + } + } + } + } + // Parse ATTR_MEMORY_MAP + TCFLaunchDelegate.getMemMapsAttribute(maps, cfg); + } + private void readPathMapConfiguration(ILaunchConfiguration cfg) throws CoreException { String s = cfg.getAttribute(TCFLaunchDelegate.ATTR_PATH_MAP, ""); host_path_map = TCFLaunchDelegate.parsePathMapAttribute(s); @@ -1212,7 +1275,7 @@ public class TCFLaunch extends Launch { public void onLastContextRemoved() { ILaunchConfiguration cfg = getLaunchConfiguration(); try { - if (cfg.getAttribute(TCFLaunchDelegate.ATTR_DISCONNECT_ON_CTX_EXIT, true)) { + if (process != null && cfg.getAttribute(TCFLaunchDelegate.ATTR_DISCONNECT_ON_CTX_EXIT, true)) { last_context_exited = true; closeChannel(); } |