Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/org.eclipse.tcf.debug.ui/src')
-rw-r--r--plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/ImageCache.java2
-rw-r--r--plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/ContextListControl.java653
-rw-r--r--plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/ContextSelection.java19
-rw-r--r--plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/ContextSelectionDialog.java115
-rw-r--r--plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/DownloadFileDialog.java400
-rw-r--r--plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/FileSystemBrowserControl.java515
-rw-r--r--plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/PeerListControl.java743
-rw-r--r--plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/RemoteFileSelectionDialog.java170
-rw-r--r--plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFDownloadTab.java361
-rw-r--r--plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFMainTab.java13
-rw-r--r--plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFPathMapTab.java4
-rw-r--r--plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFTabGroup.java3
-rw-r--r--plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFTargetTab.java619
-rw-r--r--plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModel.java8
14 files changed, 3017 insertions, 608 deletions
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.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/ContextSelection.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/ContextSelection.java
new file mode 100644
index 000000000..3337782ea
--- /dev/null
+++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/ContextSelection.java
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * 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;
+
+public class ContextSelection {
+ public String fPeerId;
+ public String fContextId;
+ public String fContextFullName;
+ public String fContextName;
+ public boolean fIsAttached;
+}
diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/ContextSelectionDialog.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/ContextSelectionDialog.java
new file mode 100644
index 000000000..5c284d425
--- /dev/null
+++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/ContextSelectionDialog.java
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * 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 org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.window.IShellProvider;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.widgets.Composite;
+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.debug.ui.launch.PeerListControl.PeerInfo;
+import org.eclipse.tcf.internal.debug.ui.launch.ContextListControl.ContextInfo;
+
+/**
+ * Dialog to select a peer and context.
+ */
+public class ContextSelectionDialog extends Dialog {
+
+ private final boolean processes;
+ private ContextSelection selection;
+ private ContextListControl context_list;
+
+ public ContextSelectionDialog(IShellProvider parentShell, boolean processes) {
+ super(parentShell);
+ this.processes = processes;
+ }
+
+ public void setSelection(ContextSelection selection) {
+ this.selection = selection;
+ }
+
+ public ContextSelection getSelection() {
+ return selection;
+ }
+
+ @Override
+ protected void configureShell(Shell shell) {
+ shell.setText("Select Peer and Context");
+ super.configureShell(shell);
+ }
+
+ @Override
+ protected Control createContents(Composite parent) {
+ Control control = super.createContents(parent);
+ updateButtonState();
+ return control;
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ Composite composite = (Composite) super.createDialogArea(parent);
+ new Label(composite, SWT.NONE).setText("Peers:");
+ final PeerListControl peerList = new PeerListControl(composite) {
+ @Override
+ protected void onPeerSelected(PeerInfo info) {
+ handlePeerSelected(info);
+ }
+ };
+ 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) {
+ ContextInfo contextInfo = context_list.findInfo((TreeItem) e.item);
+ if (contextInfo != null) {
+ handleContextSelected(contextInfo);
+ }
+ }
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ widgetSelected(e);
+ if (getButton(IDialogConstants.OK_ID).isEnabled()) {
+ buttonPressed(IDialogConstants.OK_ID);
+ }
+ }
+ });
+ 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(selection.fContextId != null);
+ }
+
+ 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 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.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/FileSystemBrowserControl.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/FileSystemBrowserControl.java
new file mode 100644
index 000000000..ce8da20bf
--- /dev/null
+++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/FileSystemBrowserControl.java
@@ -0,0 +1,515 @@
+/*******************************************************************************
+ * 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.Arrays;
+import java.util.Comparator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.core.runtime.Path;
+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.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.IFileSystem;
+import org.eclipse.tcf.services.IFileSystem.DirEntry;
+import org.eclipse.tcf.services.IFileSystem.FileSystemException;
+import org.eclipse.tcf.services.IFileSystem.IFileHandle;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+
+public class FileSystemBrowserControl {
+
+ static class FileInfo {
+ String name;
+ String fullname;
+ boolean isDir;
+ FileInfo[] children;
+ Throwable children_error;
+ int index;
+ boolean children_pending;
+ FileInfo parent;
+ }
+
+ private Tree fileTree;
+ private Display fDisplay;
+ private IPeer fPeer;
+ private final FileInfo fRootInfo = new FileInfo();
+ private IChannel fChannel;
+ private IFileSystem fFileSystem;
+ private String fFileToSelect;
+ private LinkedList<String> fPathToSelect;
+ private FileInfo fLastSelectedFileInfo;
+ private final boolean fDirectoriesOnly;
+
+ public FileSystemBrowserControl(Composite parent, boolean directoriesOnly) {
+ fDirectoriesOnly = directoriesOnly;
+ fDisplay = parent.getDisplay();
+ parent.addDisposeListener(new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ handleDispose();
+ }
+ });
+ createFileListArea(parent);
+ }
+
+ public void setInput(IPeer peer) {
+ if (peer == fPeer) {
+ return;
+ }
+ if (fPeer != null) {
+ Protocol.invokeAndWait(new Runnable() {
+ public void run() {
+ disconnectPeer();
+ }
+ });
+ }
+ fileTree.setItemCount(0);
+ fRootInfo.children = null;
+ fPeer = peer;
+ if (fPeer != null) {
+ Protocol.invokeAndWait(new Runnable() {
+ public void run() {
+ connectPeer();
+ }
+ });
+ }
+ }
+
+ public Tree getTree() {
+ return fileTree;
+ }
+
+ private void createFileListArea(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));
+
+ fileTree = new Tree(composite, SWT.VIRTUAL | SWT.BORDER | SWT.SINGLE);
+ GridData gd = new GridData(GridData.FILL_BOTH);
+ gd.minimumHeight = 300;
+ gd.minimumWidth = 350;
+ fileTree.setLayoutData(gd);
+ fileTree.setFont(font);
+ fileTree.addListener(SWT.SetData, new Listener() {
+ public void handleEvent(Event event) {
+ TreeItem item = (TreeItem)event.item;
+ FileInfo info = findFileInfo(item);
+ if (info == null) {
+ updateItems(item.getParentItem(), false);
+ }
+ else {
+ fillItem(item, info);
+ }
+ }
+ });
+ }
+
+ private void handleDispose() {
+ Protocol.invokeAndWait(new Runnable() {
+ public void run() {
+ disconnectPeer();
+ fFileSystem = null;
+ fDisplay = null;
+ }
+ });
+ }
+
+ protected void disconnectPeer() {
+ if (fChannel != null && fChannel.getState() != IChannel.STATE_CLOSED) {
+ fChannel.close();
+ }
+ }
+
+ protected void connectPeer() {
+ final IChannel channel = fPeer.openChannel();
+ fChannel = channel;
+ fFileSystem = null;
+ channel.addChannelListener(new IChannelListener() {
+ public void congestionLevel(int level) {
+ }
+ public void onChannelClosed(final Throwable error) {
+ if (fChannel != channel) return;
+ fChannel = null;
+ if (fDisplay != null) {
+ fDisplay.asyncExec(new Runnable() {
+ public void run() {
+ if (fRootInfo.children_pending) return;
+ fRootInfo.children = null;
+ fRootInfo.children_error = error;
+ updateItems(fRootInfo);
+ }
+ });
+ }
+ }
+ public void onChannelOpened() {
+ if (fChannel != channel) return;
+ fFileSystem = fChannel.getRemoteService(IFileSystem.class);
+ if (fFileSystem != null) {
+ if (fFileToSelect != null && fFileToSelect.length() > 0) {
+ final LinkedList<String> filePath = new LinkedList<String>();
+ filePath.addAll(Arrays.asList(fFileToSelect.split("[/\\\\]", -1)));
+ if (fFileToSelect.charAt(0) == '/') {
+ filePath.set(0, "/");
+ }
+ fPathToSelect = filePath;
+ fLastSelectedFileInfo = fRootInfo;
+ }
+ }
+ if (fDisplay != null) {
+ fDisplay.asyncExec(new Runnable() {
+ public void run() {
+ if (fRootInfo.children_pending) return;
+ fRootInfo.children = null;
+ fRootInfo.children_error = null;
+ updateItems(fRootInfo);
+ }
+ });
+ }
+ }
+ });
+ }
+
+ private void updateItems(TreeItem parent_item, boolean reload) {
+ final FileInfo parent_info = findFileInfo(parent_item);
+ if (parent_info == null) {
+ parent_item.setText("Invalid");
+ }
+ else {
+ if (reload && parent_info.children_error != null) {
+ loadChildren(parent_info);
+ }
+ fDisplay.asyncExec(new Runnable() {
+ public void run() {
+ updateItems(parent_info);
+ }
+ });
+ }
+ }
+
+ private void updateItems(final FileInfo parent) {
+ if (fDisplay == null) return;
+ assert Thread.currentThread() == fDisplay.getThread();
+ TreeItem[] items = null;
+ boolean expanded = true;
+ if (parent.children == null || parent.children_error != null) {
+ if (parent == fRootInfo) {
+ fileTree.setItemCount(1);
+ items = fileTree.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(fDisplay.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(fDisplay.getSystemColor(SWT.COLOR_RED));
+ items[0].setText(msg);
+ items[0].setImage((Image) null);
+ }
+ else if (expanded) {
+ loadChildren(parent);
+ items[0].setForeground(fDisplay.getSystemColor(SWT.COLOR_LIST_FOREGROUND));
+ items[0].setText("Pending...");
+ }
+ else {
+ items[0].setText("");
+ }
+ }
+ else {
+ FileInfo[] arr = parent.children;
+ if (parent == fRootInfo) {
+ fileTree.setItemCount(arr.length);
+ items = fileTree.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]);
+ expandSelect();
+ }
+ else {
+ items[0].setText("");
+ }
+ }
+ }
+
+ private void expandSelect() {
+ if (fPathToSelect == null) return;
+ if (fPathToSelect.isEmpty()) {
+ fPathToSelect = null;
+ fFileToSelect = null;
+ return;
+ }
+ do {
+ String name = fPathToSelect.getFirst();
+ if (name.length() == 0) {
+ fPathToSelect.removeFirst();
+ continue;
+ }
+ FileInfo info = findFileInfo(fLastSelectedFileInfo, name);
+ if (info == null) break;
+ TreeItem item = findItem(info);
+ if (item == null) break;
+ fPathToSelect.removeFirst();
+ if (fPathToSelect.isEmpty()) {
+ fileTree.setSelection(item);
+ fileTree.showItem(item);
+ } else {
+ item.setExpanded(true);
+ fileTree.showItem(item);
+ }
+ fLastSelectedFileInfo = info;
+ } while (!fPathToSelect.isEmpty());
+ }
+
+ private void loadChildren(final FileInfo parent) {
+ assert Thread.currentThread() == fDisplay.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 IFileSystem fs = fFileSystem;
+ if (fs == null || !canHaveChildren(parent)) {
+ doneLoadChildren(parent, null, new FileInfo[0]);
+ return;
+ }
+ if (parent.fullname == null) {
+ fs.roots(new IFileSystem.DoneRoots() {
+ public void doneRoots(IToken token, FileSystemException error, DirEntry[] entries) {
+ if (error != null) {
+ doneLoadChildren(parent, error, null);
+ } else {
+ final List<FileInfo> fileInfos = new ArrayList<FileInfo>(entries.length);
+ for (DirEntry entry : entries) {
+ FileInfo info = new FileInfo();
+ info.parent = parent;
+ String name = entry.filename;
+ int length = name.length();
+ if (length > 1 && (name.endsWith("\\") || name.endsWith("/"))) {
+ name = name.substring(0, length - 1);
+ }
+ info.name = name;
+ info.fullname = entry.longname != null ? entry.longname : entry.filename;
+ info.isDir = entry.attrs != null ? entry.attrs.isDirectory() : false;
+ if (!fDirectoriesOnly || info.isDir) {
+ fileInfos.add(info);
+ }
+ }
+ doneLoadChildren(parent, null, fileInfos.toArray(new FileInfo[fileInfos.size()]));
+ }
+ }
+ });
+ return;
+ }
+ fs.opendir(parent.fullname, new IFileSystem.DoneOpen() {
+ final List<FileInfo> fileInfos = new ArrayList<FileInfo>();
+ public void doneOpen(IToken token, FileSystemException error, final IFileHandle handle) {
+ if (error != null) {
+ doneLoadChildren(parent, error, null);
+ return;
+ }
+ fs.readdir(handle, new IFileSystem.DoneReadDir() {
+ public void doneReadDir(IToken token, FileSystemException error, DirEntry[] entries, boolean eof) {
+ if (entries != null) {
+ for (DirEntry entry : entries) {
+ FileInfo info = new FileInfo();
+ info.parent = parent;
+ info.name = entry.filename;
+ info.fullname = entry.longname != null ? entry.longname : (new Path(parent.fullname).append(info.name).toString());
+ info.isDir = entry.attrs != null ? entry.attrs.isDirectory() : false;
+ if (!fDirectoriesOnly || info.isDir) {
+ fileInfos.add(info);
+ }
+ }
+ }
+ if (error != null || eof) {
+ fs.close(handle, new IFileSystem.DoneClose() {
+ public void doneClose(IToken token, FileSystemException error) {
+ // ignore error
+ }
+ });
+ int size = fileInfos.size();
+ if (size == 0 && error != null) {
+ doneLoadChildren(parent, error, null);
+ } else {
+ doneLoadChildren(parent, null, fileInfos.toArray(new FileInfo[size]));
+ }
+ } else {
+ fs.readdir(handle, this);
+ }
+ }
+ });
+ }
+ });
+ }
+ });
+ }
+
+ private void doneLoadChildren(final FileInfo parent, final Throwable error, final FileInfo[] children) {
+ assert Protocol.isDispatchThread();
+ assert error == null || children == null;
+ if (fDisplay == null) return;
+ Arrays.sort(children, new Comparator<FileInfo>() {
+ public int compare(FileInfo o1, FileInfo o2) {
+ if (o1.isDir == o2.isDir)
+ return o1.name.compareTo(o2.name);
+ if (o1.isDir) return 1;
+ return -1;
+ }});
+ int i = 0;
+ for (FileInfo fileInfo : children) {
+ fileInfo.index = i++;
+ }
+ fDisplay.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 FileInfo findFileInfo(TreeItem item) {
+ assert Thread.currentThread() == fDisplay.getThread();
+ if (item == null) return fRootInfo ;
+ TreeItem parent = item.getParentItem();
+ FileInfo info = findFileInfo(parent);
+ if (info == null) return null;
+ if (info.children == null) return null;
+ if (info.children_error != null) return null;
+ int i = parent == null ? fileTree.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 FileInfo findFileInfo(FileInfo parent, String name) {
+ assert Thread.currentThread() == fDisplay.getThread();
+ if (name == null) return fRootInfo;
+ if (name.equals(parent.name)) return parent;
+ FileInfo[] childInfos = parent.children;
+ if (childInfos != null) {
+ for (FileInfo fileInfo : childInfos) {
+ FileInfo found = findFileInfo(fileInfo, name);
+ if (found != null) {
+ return found;
+ }
+ }
+ }
+ return null;
+ }
+
+ private TreeItem findItem(FileInfo info) {
+ if (info == null) return null;
+ assert info.parent != null;
+ if (info.parent == fRootInfo) {
+ int n = fileTree.getItemCount();
+ if (info.index >= n) return null;
+ return fileTree.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, FileInfo info) {
+ assert Thread.currentThread() == fDisplay.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.fullname;
+ item.setText(text);
+ item.setForeground(fDisplay.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(FileInfo info) {
+ return info.isDir || info == fRootInfo;
+ }
+
+ private Image getImage(FileInfo info) {
+ if (info.isDir) {
+ return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FOLDER);
+ } else {
+ return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FILE);
+ }
+ }
+
+ public void setInitialSelection(final String filename) {
+ fPathToSelect = null;
+ Protocol.invokeLater(new Runnable() {
+ public void run() {
+ fFileToSelect = filename;
+ }
+ });
+ }
+
+ public FileInfo getSelection() {
+ if (fileTree != null) {
+ TreeItem[] items = fileTree.getSelection();
+ if (items.length > 0) {
+ FileInfo info = findFileInfo(items[0]);
+ return info;
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/PeerListControl.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/PeerListControl.java
new file mode 100644
index 000000000..82f7aadb8
--- /dev/null
+++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/PeerListControl.java
@@ -0,0 +1,743 @@
+/*******************************************************************************
+ * 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.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+
+import org.eclipse.core.runtime.ListenerList;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+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.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+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.TreeColumn;
+import org.eclipse.swt.widgets.TreeItem;
+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.IPeer;
+import org.eclipse.tcf.protocol.Protocol;
+import org.eclipse.tcf.services.ILocator;
+
+// Cloned from TCFTargetTab
+public class PeerListControl implements ISelectionProvider {
+
+ private Tree peer_tree;
+ private final PeerInfo peer_info = new PeerInfo();
+ private Display display;
+ private final ListenerList selection_listeners = new ListenerList(ListenerList.IDENTITY);
+ private String initial_peer_id;
+
+ public static class PeerInfo {
+ public String id;
+ public IPeer peer;
+
+ PeerInfo parent;
+ Map<String,String> attrs;
+ PeerInfo[] children;
+ boolean children_pending;
+ Throwable children_error;
+ 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 PeerListControl(Composite parent) {
+ display = parent.getDisplay();
+ parent.addDisposeListener(new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ handleDispose();
+ }
+ });
+ loadChildren(peer_info);
+ createPeerListArea(parent);
+ }
+
+ 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() {
+ return peer_tree;
+ }
+
+ 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() {
+ @Override
+ 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);
+ 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);
+ }
+ });
+ }
+
+ private void handleDispose() {
+ Protocol.invokeAndWait(new Runnable() {
+ public void run() {
+ disconnectPeer(peer_info);
+ display = null;
+ }
+ });
+ }
+
+ 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 = 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);
+ }
+ });
+ 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], "");
+ }
+ }
+ 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 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 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;
+ }
+
+ 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;
+ 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) {
+ 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(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 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) {
+ selection_listeners.add(listener);
+ }
+
+ public ISelection getSelection() {
+ TreeItem[] items = peer_tree.getSelection();
+ PeerInfo[] peers = new PeerInfo[items.length];
+ int i = 0;
+ for (TreeItem item : items) {
+ peers[i++] = findPeerInfo(item);
+ }
+ return new StructuredSelection(peers);
+ }
+
+ public void removeSelectionChangedListener(ISelectionChangedListener listener) {
+ selection_listeners.remove(listener);
+ }
+
+ public void setSelection(ISelection selection) {
+ peer_tree.deselectAll();
+ if (selection instanceof IStructuredSelection) {
+ Object[] elements = ((IStructuredSelection) selection).toArray();
+ for (Object object : elements) {
+ if (object instanceof PeerInfo) {
+ TreeItem item = findItem((PeerInfo) object);
+ if (item != null) {
+ peer_tree.select(item);
+ }
+ }
+ }
+ }
+ }
+
+ private void fireSelectionChangedEvent() {
+ SelectionChangedEvent event = new SelectionChangedEvent(this, getSelection());
+ Object[] listeners = selection_listeners.getListeners();
+ for (Object listener : listeners) {
+ try {
+ ((ISelectionChangedListener) listener).selectionChanged(event);
+ }
+ catch (Exception e) {
+ Activator.log(e);
+ }
+ }
+ }
+
+ protected void onPeerListChanged() {
+ }
+
+ protected void onPeerSelected(PeerInfo info) {
+ }
+}
diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/RemoteFileSelectionDialog.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/RemoteFileSelectionDialog.java
new file mode 100644
index 000000000..ca8b5e949
--- /dev/null
+++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/RemoteFileSelectionDialog.java
@@ -0,0 +1,170 @@
+/*******************************************************************************
+ * 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 org.eclipse.core.runtime.Path;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.window.IShellProvider;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.FocusAdapter;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+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.debug.ui.launch.FileSystemBrowserControl.FileInfo;
+import org.eclipse.tcf.protocol.IPeer;
+
+/**
+ * Dialog to select a remote file.
+ */
+public class RemoteFileSelectionDialog extends Dialog {
+
+ private String fSelection;
+ private FileSystemBrowserControl fFileList;
+ private IPeer fPeer;
+ private boolean fForSave;
+ private Text fFileNameText;
+
+ public RemoteFileSelectionDialog(IShellProvider parentShell, int style) {
+ super(parentShell);
+ setShellStyle(getShellStyle() | SWT.RESIZE);
+ fForSave = (style & SWT.SAVE) != 0;
+ }
+
+ public void setPeer(IPeer peer) {
+ fPeer = peer;
+ if (fFileList != null) {
+ fFileList.setInput(peer);
+ }
+ }
+
+ public void setSelection(String fileSelection) {
+ fSelection = fileSelection;
+ }
+
+ public String getSelection() {
+ return fSelection;
+ }
+
+ @Override
+ protected void configureShell(Shell newShell) {
+ newShell.setText("Select File");
+ super.configureShell(newShell);
+ }
+
+ @Override
+ protected Control createContents(Composite parent) {
+ Control control = super.createContents(parent);
+ updateButtonState();
+ return control;
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ Composite composite = (Composite) super.createDialogArea(parent);
+ fFileList = new FileSystemBrowserControl(composite, false);
+ fFileList.getTree().addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ FileInfo contextInfo = fFileList.findFileInfo((TreeItem) e.item);
+ if (contextInfo != null) {
+ handleFileSelected(contextInfo);
+ }
+ }
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ widgetSelected(e);
+ if (getButton(IDialogConstants.OK_ID).isEnabled()) {
+ buttonPressed(IDialogConstants.OK_ID);
+ }
+ }
+ });
+
+ if (fForSave) {
+ Composite fileNameComp = new Composite(composite, SWT.NONE);
+ fileNameComp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+ GridLayout layout = new GridLayout(2, false);
+ layout.marginWidth = 0;
+ fileNameComp.setLayout(layout);
+ new Label(fileNameComp, SWT.NONE).setText("File Name:");
+ fFileNameText = new Text(fileNameComp, SWT.BORDER);
+ fFileNameText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+ fFileNameText.addFocusListener(new FocusAdapter() {
+ @Override
+ public void focusLost(FocusEvent e) {
+ handleFileNameChanged();
+ }
+ });
+ }
+
+ if (fSelection != null) {
+ fFileList.setInitialSelection(fSelection);
+ if (fFileNameText != null) {
+ String basename = new Path(fSelection).lastSegment();
+ if (basename != null) {
+ fFileNameText.setText(basename);
+ }
+ }
+ }
+ if (fPeer != null) {
+ fFileList.setInput(fPeer);
+ }
+ return composite;
+ }
+
+ private void updateButtonState() {
+ boolean enabled = fSelection != null;
+ if (enabled && fForSave) {
+ enabled = fFileNameText.getText().trim().length() > 0;
+ }
+ getButton(IDialogConstants.OK_ID).setEnabled(enabled);
+ }
+
+ protected void handleFileNameChanged() {
+ if (fSelection != null) {
+ fSelection = new Path(fSelection).removeLastSegments(1).append(fFileNameText.getText().trim()).toString();
+ updateButtonState();
+ }
+ }
+
+ protected void handleFileSelected(FileInfo fileInfo) {
+ if (fileInfo.isDir) {
+ if (fForSave) {
+ String basename = fFileNameText.getText().trim();
+ if (basename.length() > 0) {
+ fSelection = new Path(fileInfo.fullname).append(basename).toString();
+ } else {
+ fSelection = fileInfo.fullname;
+ }
+ } else {
+ fSelection = null;
+ }
+ } else {
+ fSelection = fileInfo.fullname;
+ if (fFileNameText != null) {
+ String basename = new Path(fSelection).lastSegment();
+ if (basename != null) {
+ fFileNameText.setText(basename);
+ }
+ }
+ }
+ updateButtonState();
+ }
+
+}
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) {

Back to the top