/*******************************************************************************
* Copyright (c) 2007, 2011 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.tm.internal.tcf.debug.ui.launch;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Platform;
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.window.Window;
import org.eclipse.jface.wizard.WizardDialog;
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;
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.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;
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.tm.internal.tcf.debug.launch.TCFLaunchDelegate;
import org.eclipse.tm.internal.tcf.debug.launch.TCFLocalAgent;
import org.eclipse.tm.internal.tcf.debug.launch.TCFUserDefPeer;
import org.eclipse.tm.internal.tcf.debug.tests.TCFTestSuite;
import org.eclipse.tm.internal.tcf.debug.ui.Activator;
import org.eclipse.tm.internal.tcf.debug.ui.ImageCache;
import org.eclipse.tm.internal.tcf.debug.ui.launch.setup.SetupWizardDialog;
import org.eclipse.tm.tcf.protocol.IChannel;
import org.eclipse.tm.tcf.protocol.IPeer;
import org.eclipse.tm.tcf.protocol.Protocol;
import org.eclipse.tm.tcf.services.ILocator;
import org.eclipse.tm.tcf.services.IMemoryMap;
import org.eclipse.tm.tcf.services.IPathMap;
import org.eclipse.tm.tcf.util.TCFTask;
/**
* Launch configuration dialog tab to specify the Target Communication Framework
* configuration.
*/
public class TCFTargetTab extends AbstractLaunchConfigurationTab {
private static final String TAB_ID = "org.eclipse.tm.tcf.launch.targetTab";
private Button run_local_agent_button;
private Button use_local_agent_button;
private Text peer_id_text;
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;
int index;
String id;
Map<String,String> attrs;
PeerInfo[] children;
boolean children_pending;
Throwable children_error;
IPeer peer;
IChannel channel;
ILocator locator;
LocatorListener listener;
}
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.index = arr.length;
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 {
arr[i].index = j;
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;
Font font = parent.getFont();
Composite comp = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout(1, true);
comp.setLayout(layout);
comp.setFont(font);
GridData gd = new GridData(GridData.FILL_BOTH);
comp.setLayoutData(gd);
setControl(comp);
createVerticalSpacer(comp, 1);
createLocalAgentButtons(comp);
createVerticalSpacer(comp, 1);
createTargetGroup(comp);
}
private void createLocalAgentButtons(Composite parent) {
Composite local_agent_comp = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout();
layout.numColumns = 1;
layout.marginHeight = 0;
layout.marginWidth = 0;
local_agent_comp.setLayout(layout);
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
local_agent_comp.setLayoutData(gd);
run_local_agent_button = createCheckButton(local_agent_comp, "Run instance of TCF agent on the local host");
run_local_agent_button.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent evt) {
updateLaunchConfigurationDialog();
}
});
run_local_agent_button.setEnabled(true);
use_local_agent_button = createCheckButton(local_agent_comp, "Use local host as a target");
use_local_agent_button.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent evt) {
updateLaunchConfigurationDialog();
}
});
use_local_agent_button.setEnabled(true);
}
private void createTargetGroup(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("Target");
createVerticalSpacer(group, layout.numColumns);
Label host_label = new Label(group, SWT.NONE);
host_label.setText("Target ID:");
host_label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING));
host_label.setFont(font);
peer_id_text = new Text(group, SWT.SINGLE | SWT.BORDER);
peer_id_text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
peer_id_text.setFont(font);
peer_id_text.setEditable(false);
createVerticalSpacer(group, layout.numColumns);
Label peer_label = new Label(group, SWT.NONE);
peer_label.setText("&Available targets:");
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 < 5; 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("Transport");
column.setWidth(60);
break;
case 3:
column.setText("Host");
column.setWidth(100);
break;
case 4:
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();
}
});
}
@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));
}
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);
}
});
createPeerButtons(composite);
}
private void createPeerButtons(Composite parent) {
Font font = parent.getFont();
Composite composite = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout();
composite.setFont(font);
composite.setLayout(layout);
composite.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL));
Menu menu = new Menu(peer_tree);
SelectionAdapter sel_adapter = null;
final Button button_new = new Button(composite, SWT.PUSH);
button_new.setText("N&ew...");
button_new.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
button_new.addSelectionListener(sel_adapter = new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
final Map<String,String> attrs = new HashMap<String,String>();
SetupWizardDialog wizard = new SetupWizardDialog(attrs);
WizardDialog dialog = new WizardDialog(getShell(), wizard);
dialog.create();
if (dialog.open() != Window.OK) return;
if (attrs.isEmpty()) return;
Protocol.invokeLater(new Runnable() {
public void run() {
new TCFUserDefPeer(attrs);
TCFUserDefPeer.savePeers();
}
});
}
});
final MenuItem item_new = new MenuItem(menu, SWT.PUSH);
item_new.setText("N&ew...");
item_new.addSelectionListener(sel_adapter);
final Button button_edit = new Button(composite, SWT.PUSH);
button_edit.setText("E&dit...");
button_edit.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
button_edit.addSelectionListener(sel_adapter = new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
final PeerInfo info = findPeerInfo(peer_id_text.getText());
if (info == null) return;
if (new PeerPropsDialog(getShell(), getImage(), info.attrs,
info.peer instanceof TCFUserDefPeer).open() != Window.OK) return;
if (!(info.peer instanceof TCFUserDefPeer)) return;
Protocol.invokeLater(new Runnable() {
public void run() {
((TCFUserDefPeer)info.peer).updateAttributes(info.attrs);
TCFUserDefPeer.savePeers();
}
});
}
});
final MenuItem item_edit = new MenuItem(menu, SWT.PUSH);
item_edit.setText("E&dit...");
item_edit.addSelectionListener(sel_adapter);
final Button button_remove = new Button(composite, SWT.PUSH);
button_remove.setText("&Remove");
button_remove.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
button_remove.addSelectionListener(sel_adapter = new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
final PeerInfo info = findPeerInfo(peer_id_text.getText());
if (info == null) return;
if (!(info.peer instanceof TCFUserDefPeer)) return;
peer_id_text.setText("");
updateLaunchConfigurationDialog();
Protocol.invokeAndWait(new Runnable() {
public void run() {
((TCFUserDefPeer)info.peer).dispose();
TCFUserDefPeer.savePeers();
}
});
}
});
final MenuItem item_remove = new MenuItem(menu, SWT.PUSH);
item_remove.setText("&Remove");
item_remove.addSelectionListener(sel_adapter);
createVerticalSpacer(composite, 20);
new MenuItem(menu, SWT.SEPARATOR);
final Button button_test = new Button(composite, SWT.PUSH);
button_test.setText("Run &Tests");
button_test.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
button_test.addSelectionListener(sel_adapter = new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
runDiagnostics(false);
}
});
final MenuItem item_test = new MenuItem(menu, SWT.PUSH);
item_test.setText("Run &Tests");
item_test.addSelectionListener(sel_adapter);
final Button button_loop = new Button(composite, SWT.PUSH);
button_loop.setText("Tests &Loop");
button_loop.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
button_loop.addSelectionListener(sel_adapter = new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
runDiagnostics(true);
}
});
final MenuItem item_loop = new MenuItem(menu, SWT.PUSH);
item_loop.setText("Tests &Loop");
item_loop.addSelectionListener(sel_adapter);
peer_tree.setMenu(menu);
update_peer_buttons = new Runnable() {
public void run() {
boolean local = use_local_agent_button.getSelection();
PeerInfo info = 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);
button_test.setEnabled(local || info != null);
button_loop.setEnabled(local || info != null);
item_new.setEnabled(!local);
item_edit.setEnabled(info != null && !local);
item_remove.setEnabled(info != null && info.peer instanceof TCFUserDefPeer && !local);
item_test.setEnabled(info != null);
item_loop.setEnabled(info != null);
}
};
update_peer_buttons.run();
}
@Override
protected void updateLaunchConfigurationDialog() {
if (use_local_agent_button.getSelection()) {
peer_tree.setEnabled(false);
peer_tree.deselectAll();
String id = TCFLocalAgent.getLocalAgentID();
if (id == null) id = "";
peer_id_text.setText(id);
peer_id_text.setEnabled(false);
}
else {
peer_tree.setEnabled(true);
peer_id_text.setEnabled(true);
String id = peer_id_text.getText();
TreeItem item = findItem(findPeerInfo(id));
if (item != null) peer_tree.setSelection(item);
else peer_tree.deselectAll();
}
update_peer_buttons.run();
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";
}
@Override
public Image getImage() {
return ImageCache.getImage(ImageCache.IMG_TARGET_TAB);
}
@Override
public String getId() {
return TAB_ID;
}
public void initializeFrom(ILaunchConfiguration configuration) {
setErrorMessage(null);
setMessage(null);
try {
String id = configuration.getAttribute(TCFLaunchDelegate.ATTR_PEER_ID, "");
TreeItem item = findItem(findPeerInfo(id));
if (item != null) peer_tree.setSelection(item);
peer_id_text.setText(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");
}
catch (CoreException e) {
init_error = e;
setErrorMessage("Cannot read launch configuration: " + e);
Activator.log(e);
}
updateLaunchConfigurationDialog();
}
public void performApply(ILaunchConfigurationWorkingCopy configuration) {
if (use_local_agent_button.getSelection()) {
configuration.removeAttribute(TCFLaunchDelegate.ATTR_PEER_ID);
}
else {
configuration.setAttribute(TCFLaunchDelegate.ATTR_PEER_ID, peer_id_text.getText());
}
configuration.setAttribute(TCFLaunchDelegate.ATTR_RUN_LOCAL_AGENT, run_local_agent_button.getSelection());
configuration.setAttribute(TCFLaunchDelegate.ATTR_USE_LOCAL_AGENT, use_local_agent_button.getSelection());
}
public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {
configuration.setAttribute(TCFLaunchDelegate.ATTR_RUN_LOCAL_AGENT, false);
configuration.setAttribute(TCFLaunchDelegate.ATTR_USE_LOCAL_AGENT, true);
configuration.removeAttribute(TCFLaunchDelegate.ATTR_PEER_ID);
}
@Override
public boolean isValid(ILaunchConfiguration config) {
setErrorMessage(null);
setMessage(null);
if (init_error != null) {
setErrorMessage("Cannot read launch configuration: " + init_error);
return false;
}
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.index = n;
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 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();
TreeItem[] items = null;
boolean expanded = true;
if (parent.children == null || parent.children_error != null) {
if (parent == peer_info) {
peer_tree.setItemCount(1);
items = peer_tree.getItems();
}
else {
TreeItem item = findItem(parent);
if (item == null) return;
expanded = item.getExpanded();
item.setItemCount(1);
items = item.getItems();
}
assert items.length == 1;
items[0].removeAll();
if (parent.children_pending) {
items[0].setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND));
items[0].setText("Connecting...");
}
else if (parent.children_error != null) {
String msg = parent.children_error.getMessage();
if (msg == null) msg = parent.children_error.getClass().getName();
else msg = msg.replace('\n', ' ');
items[0].setForeground(display.getSystemColor(SWT.COLOR_RED));
items[0].setText(msg);
}
else if (expanded) {
loadChildren(parent);
items[0].setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND));
items[0].setText("Connecting...");
}
else {
Protocol.invokeAndWait(new Runnable() {
public void run() {
disconnectPeer(parent);
}
});
items[0].setText("");
}
int n = peer_tree.getColumnCount();
for (int i = 1; i < n; i++) items[0].setText(i, "");
items[0].setImage((Image)null);
}
else {
PeerInfo[] arr = parent.children;
if (parent == peer_info) {
peer_tree.setItemCount(arr.length);
items = peer_tree.getItems();
}
else {
TreeItem item = findItem(parent);
if (item == null) return;
expanded = item.getExpanded();
item.setItemCount(expanded ? arr.length : 1);
items = item.getItems();
}
if (expanded) {
assert items.length == arr.length;
for (int i = 0; i < items.length; i++) fillItem(items[i], arr[i]);
}
else {
Protocol.invokeAndWait(new Runnable() {
public void run() {
disconnectPeer(parent);
}
});
items[0].setText("");
int n = peer_tree.getColumnCount();
for (int i = 1; i < n; i++) items[0].setText(i, "");
}
}
updateLaunchConfigurationDialog();
}
private PeerInfo findPeerInfo(TreeItem item) {
assert Thread.currentThread() == display.getThread();
if (item == null) return peer_info;
TreeItem parent = item.getParentItem();
PeerInfo info = findPeerInfo(parent);
if (info == null) return null;
if (info.children == null) return null;
if (info.children_error != null) return null;
int i = parent == null ? peer_tree.indexOf(item) : parent.indexOf(item);
if (i < 0 || i >= info.children.length) return null;
assert info.children[i].index == i;
return info.children[i];
}
private PeerInfo findPeerInfo(String path) {
assert Thread.currentThread() == display.getThread();
if (path == null) return null;
int i = path.lastIndexOf('/');
String id = null;
PeerInfo[] arr = null;
if (i < 0) {
arr = peer_info.children;
if (arr == null) return null;
id = path;
}
else {
PeerInfo p = findPeerInfo(path.substring(0, i));
if (p == null) return null;
arr = p.children;
if (arr == null) {
TreeItem item = findItem(p);
item.setExpanded(true);
return null;
}
id = path.substring(i + 1);
}
for (int n = 0; n < arr.length; n++) {
if (arr[n].id.equals(id)) return arr[n];
}
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();
if (info.index >= n) return null;
return peer_tree.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 runDiagnostics(boolean loop) {
IPeer peer = null;
if (use_local_agent_button.getSelection()) {
try {
if (run_local_agent_button.getSelection()) TCFLocalAgent.runLocalAgent();
final String id = TCFLocalAgent.getLocalAgentID();
peer = new TCFTask<IPeer>() {
public void run() {
done(Protocol.getLocator().getPeers().get(id));
}
}.get();
}
catch (Throwable err) {
String msg = err.getLocalizedMessage();
if (msg == null || msg.length() == 0) msg = err.getClass().getName();
MessageBox mb = new MessageBox(getShell(), SWT.ICON_ERROR | SWT.OK);
mb.setText("Error");
mb.setMessage("Cannot start agent:\n" + msg);
mb.open();
}
}
else {
PeerInfo info = findPeerInfo(peer_id_text.getText());
if (info == null) return;
peer = info.peer;
}
if (peer == null) return;
final Shell shell = new Shell(getShell(), SWT.TITLE | SWT.PRIMARY_MODAL);
GridLayout layout = new GridLayout();
layout.verticalSpacing = 0;
layout.numColumns = 2;
shell.setLayout(layout);
shell.setText("Running Diagnostics...");
CLabel label = new CLabel(shell, SWT.NONE);
label.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false));
label.setText("Running Diagnostics...");
final TCFTestSuite[] test = new TCFTestSuite[1];
Button button_cancel = new Button(shell, SWT.PUSH);
button_cancel.setText("&Cancel");
button_cancel.setLayoutData(new GridData(GridData.END, GridData.CENTER, false, false));
button_cancel.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
Protocol.invokeLater(new Runnable() {
public void run() {
if (test[0] != null) test[0].cancel();
}
});
}
});
createVerticalSpacer(shell, 0);
ProgressBar bar = new ProgressBar(shell, SWT.HORIZONTAL);
bar.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false, 2, 1));
shell.setDefaultButton(button_cancel);
shell.pack();
shell.setSize(483, shell.getSize().y);
Rectangle rc0 = getShell().getBounds();
Rectangle rc1 = shell.getBounds();
shell.setLocation(rc0.x + (rc0.width - rc1.width) / 2, rc0.y + (rc0.height - rc1.height) / 2);
shell.setVisible(true);
runDiagnostics(peer, loop, test, shell, label, bar);
}
private void runDiagnostics(final IPeer peer, final boolean loop, final TCFTestSuite[] test,
final Shell shell, final CLabel label, final ProgressBar bar) {
final TCFTestSuite.TestListener done = new TCFTestSuite.TestListener() {
private String last_text = "";
private int last_count = 0;
private int last_total = 0;
public void progress(final String label_text, final int count_done, final int count_total) {
assert test[0] != null;
if ((label_text == null || last_text.equals(label_text)) &&
last_total == count_total &&
(count_done - last_count) / (float)count_total < 0.02f) return;
if (label_text != null) last_text = label_text;
last_total = count_total;
last_count = count_done;
display.asyncExec(new Runnable() {
public void run() {
label.setText(last_text);
bar.setMinimum(0);
bar.setMaximum(last_total);
bar.setSelection(last_count);
}
});
}
public void done(final Collection<Throwable> errors) {
assert test[0] != null;
final boolean b = test[0].isCanceled();
test[0] = null;
display.asyncExec(new Runnable() {
public void run() {
if (errors.size() > 0) {
shell.dispose();
new TestErrorsDialog(getControl().getShell(),
ImageCache.getImage(ImageCache.IMG_TCF), errors).open();
}
else if (loop && !b && display != null) {
runDiagnostics(peer, true, test, shell, label, bar);
}
else {
shell.dispose();
}
}
});
}
};
Protocol.invokeLater(new Runnable() {
public void run() {
try {
List<IPathMap.PathMapRule> path_map = null;
for (ILaunchConfigurationTab t : getLaunchConfigurationDialog().getTabs()) {
if (t instanceof TCFPathMapTab) path_map = ((TCFPathMapTab)t).getPathMap();
}
HashMap<String,ArrayList<IMemoryMap.MemoryRegion>> mem_map = null;
if (mem_map_cfg != null) {
mem_map = new HashMap<String,ArrayList<IMemoryMap.MemoryRegion>>();
TCFLaunchDelegate.parseMemMapsAttribute(mem_map, mem_map_cfg);
}
boolean enable_tracing =
"true".equals(Platform.getDebugOption("org.eclipse.tm.tcf.debug/debug")) &&
"true".equals(Platform.getDebugOption("org.eclipse.tm.tcf.debug/debug/tests/runcontrol"));
if (enable_tracing) System.setProperty("org.eclipse.tm.tcf.debug.tracing.tests.runcontrol", "true");
test[0] = new TCFTestSuite(peer, done, path_map, mem_map);
}
catch (Throwable x) {
ArrayList<Throwable> errors = new ArrayList<Throwable>();
errors.add(x);
done.done(errors);
}
}
});
}
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[5];
text[0] = info.attrs.get(IPeer.ATTR_NAME);
text[1] = info.attrs.get(IPeer.ATTR_OS_NAME);
text[2] = info.attrs.get(IPeer.ATTR_TRANSPORT_NAME);
text[3] = info.attrs.get(IPeer.ATTR_IP_HOST);
text[4] = info.attrs.get(IPeer.ATTR_IP_PORT);
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 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;
}
}