mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Bug 360314: OS awareness debug view
Change-Id: I96b6df8bd5faa7e1da579d9e45580004170ac1e9 Reviewed-on: https://git.eclipse.org/r/5835 Reviewed-by: Marc Khouzam <marc.khouzam@ericsson.com> IP-Clean: Marc Khouzam <marc.khouzam@ericsson.com> Tested-by: Marc Khouzam <marc.khouzam@ericsson.com>
This commit is contained in:
parent
52cf5f2b85
commit
5439a6af9e
19 changed files with 2022 additions and 3 deletions
|
@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2
|
|||
Bundle-Name: %pluginName
|
||||
Bundle-Vendor: %providerName
|
||||
Bundle-SymbolicName: org.eclipse.cdt.dsf.gdb.ui;singleton:=true
|
||||
Bundle-Version: 2.3.0.qualifier
|
||||
Bundle-Version: 2.4.0.qualifier
|
||||
Bundle-Activator: org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin
|
||||
Bundle-Localization: plugin
|
||||
Require-Bundle: org.eclipse.ui,
|
||||
|
@ -32,6 +32,7 @@ Export-Package: org.eclipse.cdt.dsf.gdb.internal.ui;x-internal:=true,
|
|||
org.eclipse.cdt.dsf.gdb.internal.ui.commands;x-internal:=true,
|
||||
org.eclipse.cdt.dsf.gdb.internal.ui.console;x-internal:=true,
|
||||
org.eclipse.cdt.dsf.gdb.internal.ui.launching;x-friends:="org.eclipse.cdt.debug.gdbjtag.ui",
|
||||
org.eclipse.cdt.dsf.gdb.internal.ui.osview;x-internal:=true,
|
||||
org.eclipse.cdt.dsf.gdb.internal.ui.preferences;x-internal:=true,
|
||||
org.eclipse.cdt.dsf.gdb.internal.ui.tracepointactions;x-internal:=true,
|
||||
org.eclipse.cdt.dsf.gdb.internal.ui.tracepoints;x-internal:=true,
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 262 B |
|
@ -1,5 +1,5 @@
|
|||
###############################################################################
|
||||
# Copyright (c) 2008, 2010 Ericsson and others.
|
||||
# Copyright (c) 2008, 2012 Ericsson 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
|
||||
|
@ -9,6 +9,7 @@
|
|||
# Ericsson - initial API and implementation
|
||||
# IBM Corporation
|
||||
# Jens Elmenthaler (Verigy) - Added Full GDB pretty-printing support (bug 302121)
|
||||
# Vladimir Prus (Mentor Graphics) - OS Resources view (bug 360314)
|
||||
###############################################################################
|
||||
pluginName=GDB DSF Debugger Integration UI
|
||||
providerName=Eclipse CDT
|
||||
|
@ -47,3 +48,6 @@ activity.name = CDT DSF-GDB - GDB Debugging
|
|||
|
||||
# Pretty Printing
|
||||
action.fetchMoreChildren.label=Fetch More Children
|
||||
|
||||
# OS view
|
||||
view.osresources.name=OS Resources
|
||||
|
|
|
@ -263,6 +263,13 @@
|
|||
id="org.eclipse.cdt.dsf.gdb.ui.tracecontrol.view"
|
||||
name="%view.traceControl.name">
|
||||
</view>
|
||||
<view
|
||||
category="org.eclipse.debug.ui"
|
||||
class="org.eclipse.cdt.dsf.gdb.internal.ui.osview.OSResourcesView"
|
||||
id="org.eclipse.cdt.dsf.gdb.ui.osresources.view"
|
||||
name="%view.osresources.name"
|
||||
icon="icons/full/view16/osresources_view.gif">
|
||||
</view>
|
||||
</extension>
|
||||
<extension
|
||||
point="org.eclipse.ui.perspectiveExtensions">
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<version>2.3.0-SNAPSHOT</version>
|
||||
<version>2.4.0-SNAPSHOT</version>
|
||||
<artifactId>org.eclipse.cdt.dsf.gdb.ui</artifactId>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
</project>
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011, 2012 Mentor Graphics 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:
|
||||
* Vladimir Prus (Mentor Graphics) - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.dsf.gdb.internal.ui.osview;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
|
||||
import org.eclipse.jface.dialogs.IDialogSettings;
|
||||
|
||||
/* Hold information about which columns in a table are visible, and what
|
||||
* width they have. Stores that information inside preferences store.
|
||||
*/
|
||||
class ColumnLayout
|
||||
{
|
||||
private String fResourceClass;
|
||||
private Map<String, Boolean> fVisible = new HashMap<String, Boolean>();
|
||||
private Map<String, Integer> fWidth = new HashMap<String, Integer>();
|
||||
private Integer fSortColumn = null;
|
||||
private Integer fSortDirection = null;
|
||||
|
||||
private static IDialogSettings settings;
|
||||
private static IDialogSettings getDialogSettings()
|
||||
{
|
||||
if (settings != null)
|
||||
return settings;
|
||||
|
||||
IDialogSettings topSettings = GdbUIPlugin.getDefault().getDialogSettings();
|
||||
settings = topSettings.getSection(ResourceClassContributionItem.class.getName());
|
||||
if (settings == null) {
|
||||
settings = topSettings.addNewSection(ResourceClassContributionItem.class.getName());
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
|
||||
private static void setDefaultSetting(String key, boolean value)
|
||||
{
|
||||
IDialogSettings s = getDialogSettings();
|
||||
if (s.get(key) == null)
|
||||
s.put(key, value);
|
||||
}
|
||||
|
||||
private static void setDefaultSetting(String key, int value)
|
||||
{
|
||||
IDialogSettings s = getDialogSettings();
|
||||
if (s.get(key) == null)
|
||||
s.put(key, value);
|
||||
}
|
||||
|
||||
public ColumnLayout(String resourceClass)
|
||||
{
|
||||
fResourceClass = resourceClass;
|
||||
}
|
||||
|
||||
public boolean getVisible(String column)
|
||||
{
|
||||
if (fVisible.containsKey(column))
|
||||
return fVisible.get(column);
|
||||
else
|
||||
{
|
||||
setDefaultSetting(columnKey(column, "v"), true); //$NON-NLS-1$
|
||||
boolean b = getDialogSettings().getBoolean(columnKey(column, "v")); //$NON-NLS-1$
|
||||
fVisible.put(column, b);
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
public void setVisible(String column, boolean visible)
|
||||
{
|
||||
fVisible.put(column, visible);
|
||||
getDialogSettings().put(columnKey(column, "v"), visible); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
public int getWidth(String column)
|
||||
{
|
||||
if (fWidth.containsKey(column))
|
||||
return fWidth.get(column);
|
||||
else
|
||||
{
|
||||
setDefaultSetting(columnKey(column, "w"), -1); //$NON-NLS-1$
|
||||
int w = getDialogSettings().getInt(columnKey(column, "w")); //$NON-NLS-1$
|
||||
fWidth.put(column, w);
|
||||
return w;
|
||||
}
|
||||
}
|
||||
|
||||
public void setWidth(String column, int width)
|
||||
{
|
||||
fWidth.put(column, width);
|
||||
getDialogSettings().put(columnKey(column, "w"), width); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
public int getSortColumn()
|
||||
{
|
||||
if (fSortColumn == null)
|
||||
{
|
||||
setDefaultSetting(globalKey("sortColumn"), 0); //$NON-NLS-1$
|
||||
fSortColumn = getDialogSettings().getInt(globalKey("sortColumn")); //$NON-NLS-1$
|
||||
}
|
||||
return fSortColumn;
|
||||
}
|
||||
|
||||
public void setSortColumn(int column)
|
||||
{
|
||||
fSortColumn = column;
|
||||
getDialogSettings().put(globalKey("sortColumn"), fSortColumn); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
public int getSortDirection()
|
||||
{
|
||||
if (fSortDirection == null)
|
||||
{
|
||||
setDefaultSetting(globalKey("sortDirection"), 1); //$NON-NLS-1$
|
||||
fSortDirection = getDialogSettings().getInt(globalKey("sortDirection")); //$NON-NLS-1$
|
||||
}
|
||||
return fSortDirection;
|
||||
}
|
||||
|
||||
public void setSortDirection(int direction)
|
||||
{
|
||||
fSortDirection = direction;
|
||||
getDialogSettings().put(globalKey("sortDirection"), fSortDirection); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
private String columnKey(String column, String what)
|
||||
{
|
||||
return "columnLayout." + fResourceClass + "." + column + "." + what; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||
}
|
||||
|
||||
private String globalKey(String what)
|
||||
{
|
||||
return "columnLayout." + fResourceClass + "." + what; //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011, 2012 Mentor Graphics 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:
|
||||
* Vladimir Prus (Mentor Graphics) - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.dsf.gdb.internal.ui.osview;
|
||||
|
||||
import org.eclipse.jface.viewers.ILabelProviderListener;
|
||||
import org.eclipse.jface.viewers.IStructuredContentProvider;
|
||||
import org.eclipse.jface.viewers.ITableLabelProvider;
|
||||
import org.eclipse.jface.viewers.Viewer;
|
||||
import org.eclipse.swt.graphics.Image;
|
||||
|
||||
/** Helper class to change table and label provider of a TreeViewer in an atomic fashion.
|
||||
*
|
||||
* Suppose we want to change both content and label provider of existing TreeViewer. Right now,
|
||||
* if we set either, TreeViewer will try a refresh, using one new provider and one old. This
|
||||
* is obviously nonsensical -- for example if we set set new content provider, then old label provider
|
||||
* will be asked to provide labels for elements it has no idea what to do with, or for columns beyond
|
||||
* its range, etc.
|
||||
*
|
||||
* This class is wrapping our real content provider, and can be retargeted in one call -- after which
|
||||
* refresh of TreeViewer sees consistent data.
|
||||
*
|
||||
* @since 2.4
|
||||
* */
|
||||
public class ContentLabelProviderWrapper<U extends ITableLabelProvider & IStructuredContentProvider>
|
||||
implements ITableLabelProvider, IStructuredContentProvider
|
||||
{
|
||||
|
||||
public ContentLabelProviderWrapper(U realProvider)
|
||||
{
|
||||
this.realProvider = realProvider;
|
||||
}
|
||||
|
||||
public void setData(U realProvider)
|
||||
{
|
||||
this.realProvider = realProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image getColumnImage(Object obj, int index) {
|
||||
return realProvider.getColumnImage(obj, index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(ILabelProviderListener listener) {
|
||||
realProvider.addListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLabelProperty(Object element, String property) {
|
||||
return realProvider.isLabelProperty(element, property);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListener(ILabelProviderListener listener) {
|
||||
realProvider.removeListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getColumnText(Object obj, int index) {
|
||||
return realProvider.getColumnText(obj, index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inputChanged(Viewer v, Object oldInput, Object newInput) {
|
||||
realProvider.inputChanged(v, oldInput, newInput);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
realProvider.dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getElements(Object parent) {
|
||||
return realProvider.getElements(parent);
|
||||
}
|
||||
|
||||
private U realProvider;
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011, 2012 Mentor Graphics 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:
|
||||
* Vladimir Prus (Mentor Graphics) - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.dsf.gdb.internal.ui.osview;
|
||||
|
||||
import org.eclipse.osgi.util.NLS;
|
||||
|
||||
/**
|
||||
* @since 2.4
|
||||
*/
|
||||
public class Messages extends NLS {
|
||||
public static String OSView_3;
|
||||
public static String OSView_4;
|
||||
public static String OSView_5;
|
||||
public static String OSView_6;
|
||||
public static String OSView_7;
|
||||
public static String OSView_8;
|
||||
public static String OSView_9;
|
||||
public static String OSView_10;
|
||||
public static String OSView_11;
|
||||
public static String OSView_12;
|
||||
public static String OSView_13;
|
||||
public static String OSView_14;
|
||||
static {
|
||||
// initialize resource bundle
|
||||
NLS.initializeMessages(Messages.class.getName(), Messages.class);
|
||||
}
|
||||
|
||||
private Messages() {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
###############################################################################
|
||||
# Copyright (c) 2011, 2012 Mentor Graphics 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:
|
||||
# Vladimir Prus (Mentor Graphics) - initial API and implementation
|
||||
###############################################################################
|
||||
OSView_3=Refresh
|
||||
OSView_4=No debug session is selected.
|
||||
OSView_5=Please select resource class.
|
||||
OSView_6=Fetching data...
|
||||
OSView_7=No data has been fetched yet. <a href="{0}">Fetch now</a>.
|
||||
OSView_8='Refresh (last fetched on' h:mm:ss ')'
|
||||
OSView_9=Updating OS resources view
|
||||
OSView_10=OS resources are not available using your target and GDB.
|
||||
OSView_11=Determining available OS resource classes...
|
||||
OSView_12=No data has been fetched yet. Target is busy.
|
||||
OSView_13=Waiting for the debug session to initialize.
|
||||
OSView_14=Objects from different debug sessions are selected.
|
|
@ -0,0 +1,148 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011, 2012 Mentor Graphics 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:
|
||||
* Vladimir Prus (Mentor Graphics) - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.dsf.gdb.internal.ui.osview;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.cdt.dsf.gdb.service.IGDBHardwareAndOS2.IResourcesInformation;
|
||||
import org.eclipse.jface.viewers.IStructuredContentProvider;
|
||||
import org.eclipse.jface.viewers.ITableLabelProvider;
|
||||
import org.eclipse.jface.viewers.LabelProvider;
|
||||
import org.eclipse.jface.viewers.Viewer;
|
||||
import org.eclipse.swt.graphics.Image;
|
||||
|
||||
/* Table data provider that exposes information about OS resources
|
||||
* of specific class. Constructed from MI output. Once constructed,
|
||||
* this class is immutable.
|
||||
*/
|
||||
class OSData
|
||||
extends LabelProvider
|
||||
implements ITableLabelProvider, IStructuredContentProvider
|
||||
{
|
||||
private IResourcesInformation data;
|
||||
private boolean[] columnIsInteger;
|
||||
private List<Integer> remap;
|
||||
|
||||
public OSData(String resourceClass, IResourcesInformation data) {
|
||||
this.data = data;
|
||||
determineColumnTypes();
|
||||
|
||||
remap = new ArrayList<Integer>(data.getColumnNames().length);
|
||||
for (int i = 0; i < data.getColumnNames().length; ++i)
|
||||
remap.add(i);
|
||||
|
||||
if (resourceClass.equals("processes")) //$NON-NLS-1$
|
||||
sendToEnd("Command"); //$NON-NLS-1$
|
||||
|
||||
if (resourceClass.equals("threads")) //$NON-NLS-1$
|
||||
sendToEnd("Command"); //$NON-NLS-1$
|
||||
|
||||
if (resourceClass.equals("modules")) //$NON-NLS-1$
|
||||
sendToEnd("Dependencies"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
// Determine column types, for the purpose of proper sorting
|
||||
private void determineColumnTypes()
|
||||
{
|
||||
String[] columnNames = data.getColumnNames();
|
||||
String[][] content = data.getContent();
|
||||
|
||||
columnIsInteger = new boolean[columnNames.length];
|
||||
|
||||
boolean[] columnHasInteger = new boolean[columnNames.length];
|
||||
boolean[] columnHasOther = new boolean[columnNames.length];
|
||||
|
||||
for (int i = 0; i < content.length; ++i) {
|
||||
for (int j = 0; j < content[i].length; ++j) {
|
||||
if (!columnHasOther[j])
|
||||
{
|
||||
try {
|
||||
Integer.parseInt(content[i][j]);
|
||||
columnHasInteger[j] = true;
|
||||
}
|
||||
catch(NumberFormatException e) {
|
||||
columnHasOther[j] = true;
|
||||
}
|
||||
catch(Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < data.getColumnNames().length; ++j) {
|
||||
columnIsInteger[j] = columnHasInteger[j] && !columnHasOther[j];
|
||||
}
|
||||
}
|
||||
|
||||
/* Make column named 'column' appear last in UI. */
|
||||
private void sendToEnd(String column)
|
||||
{
|
||||
// Find index in the remap array (which is equal to index in UI)
|
||||
// at which column named 'column' is found.
|
||||
int index = -1;
|
||||
for (int i = 0; i < remap.size(); ++i)
|
||||
if (data.getColumnNames()[remap.get(i)].equals(column)) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
if (index == -1)
|
||||
return;
|
||||
|
||||
// Move the element to the end of the list
|
||||
remap.add(remap.remove(index));
|
||||
}
|
||||
|
||||
public int getColumnCount()
|
||||
{
|
||||
return remap.size();
|
||||
}
|
||||
|
||||
public String getColumnName(int i)
|
||||
{
|
||||
return data.getColumnNames()[remap.get(i)];
|
||||
}
|
||||
|
||||
public boolean getColumnIsInteger(int j) {
|
||||
return columnIsInteger[remap.get(j)];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getColumnText(Object obj, int index) {
|
||||
return ((String[]) obj)[remap.get(index)];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image getColumnImage(Object obj, int index) {
|
||||
return getImage(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image getImage(Object obj) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inputChanged(Viewer v, Object oldInput, Object newInput) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getElements(Object parent) {
|
||||
return data.getContent();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,641 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011, 2012 Mentor Graphics 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:
|
||||
* Vladimir Prus (Mentor Graphics) - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.dsf.gdb.internal.ui.osview;
|
||||
|
||||
import java.net.URL;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.Query;
|
||||
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||
import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
|
||||
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
|
||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Platform;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.core.runtime.jobs.Job;
|
||||
import org.eclipse.debug.ui.DebugUITools;
|
||||
import org.eclipse.debug.ui.contexts.DebugContextEvent;
|
||||
import org.eclipse.debug.ui.contexts.IDebugContextListener;
|
||||
import org.eclipse.debug.ui.contexts.IDebugContextManager;
|
||||
import org.eclipse.debug.ui.contexts.IDebugContextService;
|
||||
import org.eclipse.jface.action.Action;
|
||||
import org.eclipse.jface.action.IAction;
|
||||
import org.eclipse.jface.resource.ImageDescriptor;
|
||||
import org.eclipse.jface.viewers.ISelection;
|
||||
import org.eclipse.jface.viewers.IStructuredSelection;
|
||||
import org.eclipse.jface.viewers.TableViewer;
|
||||
import org.eclipse.jface.viewers.Viewer;
|
||||
import org.eclipse.jface.viewers.ViewerComparator;
|
||||
import org.eclipse.osgi.util.NLS;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.events.SelectionAdapter;
|
||||
import org.eclipse.swt.events.SelectionEvent;
|
||||
import org.eclipse.swt.layout.GridData;
|
||||
import org.eclipse.swt.layout.GridLayout;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.Event;
|
||||
import org.eclipse.swt.widgets.Link;
|
||||
import org.eclipse.swt.widgets.Listener;
|
||||
import org.eclipse.swt.widgets.Table;
|
||||
import org.eclipse.swt.widgets.TableColumn;
|
||||
import org.eclipse.ui.IActionBars;
|
||||
import org.eclipse.ui.part.ViewPart;
|
||||
import org.eclipse.ui.progress.UIJob;
|
||||
import org.osgi.framework.Bundle;
|
||||
|
||||
/**
|
||||
* @since 2.4
|
||||
*/
|
||||
public class OSResourcesView extends ViewPart implements DsfSession.SessionEndedListener {
|
||||
|
||||
private final static String FETCH_LINK_TAG = "fetch"; //$NON-NLS-1$
|
||||
|
||||
// The data model for the selected session, or null if no session is
|
||||
// selected.
|
||||
private SessionOSData fSessionData;
|
||||
private Map<String, SessionOSData> fSessionDataCache = new HashMap<String, SessionOSData>();
|
||||
// The data presently shown by table viewer.
|
||||
private OSData fTableShownData = null;
|
||||
// The data which was used to populate column selector menu
|
||||
private OSData fMenuShownData = null;
|
||||
private String fResourceClass = null;
|
||||
|
||||
// Indicates that we've selected objects from different debug sessions.
|
||||
boolean fMultiple = false;
|
||||
|
||||
|
||||
// UI objects
|
||||
private TableViewer fViewer;
|
||||
private Comparator fComparator;
|
||||
private Composite fNothingLabelContainer;
|
||||
private Link fNothingLabel;
|
||||
private ResourceClassContributionItem fResourceClassEditor;
|
||||
private Action fRefreshAction;
|
||||
|
||||
// Map from resource class name to table column layout.
|
||||
private Map<String, ColumnLayout> fColumnLayouts = new HashMap<String, ColumnLayout>();
|
||||
|
||||
private ColumnLayout fColumnLayout = null;
|
||||
|
||||
private IDebugContextListener fDebugContextListener;
|
||||
|
||||
@Override
|
||||
public void createPartControl(Composite xparent) {
|
||||
|
||||
Composite parent = new Composite(xparent, SWT.NONE);
|
||||
GridLayout topLayout = new GridLayout(1, false);
|
||||
topLayout.marginWidth = 0;
|
||||
topLayout.marginHeight = 0;
|
||||
parent.setLayout(topLayout);
|
||||
|
||||
fViewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL
|
||||
| SWT.V_SCROLL);
|
||||
GridData viewerData = new GridData(GridData.FILL_BOTH);
|
||||
viewerData.exclude = true;
|
||||
fViewer.getControl().setLayoutData(viewerData);
|
||||
|
||||
fViewer.setComparator(fComparator = new Comparator());
|
||||
|
||||
Table table = fViewer.getTable();
|
||||
table.setHeaderVisible(true);
|
||||
table.setVisible(false);
|
||||
|
||||
fNothingLabelContainer = new Composite(parent, SWT.NONE);
|
||||
|
||||
GridData nothingLayout = new GridData(SWT.FILL, SWT.FILL, true, true);
|
||||
fNothingLabelContainer.setLayoutData(nothingLayout);
|
||||
|
||||
GridLayout containerLayout = new GridLayout(1, false);
|
||||
fNothingLabelContainer.setLayout(containerLayout);
|
||||
|
||||
fNothingLabel = new Link(fNothingLabelContainer, SWT.BORDER);
|
||||
fNothingLabel.setText(Messages.OSView_4);
|
||||
fNothingLabel.setBackground(fNothingLabel.getDisplay().getSystemColor(
|
||||
SWT.COLOR_LIST_BACKGROUND));
|
||||
fNothingLabel.addListener (SWT.Selection, new Listener () {
|
||||
@Override
|
||||
public void handleEvent(Event event) {
|
||||
if (event.text.equals("fetch")) //$NON-NLS-1$
|
||||
if (fSessionData != null && fResourceClass != null)
|
||||
fSessionData.fetchData(fResourceClass);
|
||||
}
|
||||
});
|
||||
fNothingLabelContainer.setBackground(fNothingLabel.getBackground());
|
||||
|
||||
GridData nothingLabelLayout = new GridData(SWT.CENTER, SWT.TOP, true, false);
|
||||
fNothingLabel.setLayoutData(nothingLabelLayout);
|
||||
|
||||
fResourceClassEditor = new ResourceClassContributionItem();
|
||||
fResourceClassEditor.setListener(new ResourceClassContributionItem.Listener() {
|
||||
|
||||
@Override
|
||||
public void resourceClassChanged(String newClass) {
|
||||
fResourceClass = newClass;
|
||||
// Since user explicitly changed the class, initiate fetch immediately.
|
||||
fSessionData.fetchData(fResourceClass);
|
||||
// Do not call 'update()' here. fetchData call above will notify
|
||||
// us at necessary moments.
|
||||
}
|
||||
});
|
||||
IActionBars bars = getViewSite().getActionBars();
|
||||
bars.getToolBarManager().add(fResourceClassEditor);
|
||||
|
||||
fRefreshAction = new Action() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (fSessionData != null && fResourceClass != null)
|
||||
fSessionData.fetchData(fResourceClass);
|
||||
}
|
||||
};
|
||||
fRefreshAction.setText(Messages.OSView_3);
|
||||
fRefreshAction.setToolTipText(Messages.OSView_3);
|
||||
try {
|
||||
Bundle bundle= Platform.getBundle("org.eclipse.ui"); //$NON-NLS-1$
|
||||
URL url = bundle.getEntry("/"); //$NON-NLS-1$
|
||||
url = new URL(url, "icons/full/elcl16/refresh_nav.gif"); //$NON-NLS-1$
|
||||
ImageDescriptor candidate = ImageDescriptor.createFromURL(url);
|
||||
if (candidate != null && candidate.getImageData() != null) {
|
||||
fRefreshAction.setImageDescriptor(candidate);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
bars.getToolBarManager().add(fRefreshAction);
|
||||
bars.updateActionBars();
|
||||
|
||||
fResourceClass = fResourceClassEditor.getResourceClassId();
|
||||
|
||||
setupContextListener();
|
||||
DsfSession.addSessionEndedListener(this);
|
||||
}
|
||||
|
||||
private void setupContextListener() {
|
||||
IDebugContextManager contextManager = DebugUITools.getDebugContextManager();
|
||||
IDebugContextService contextService = contextManager
|
||||
.getContextService(getSite().getWorkbenchWindow());
|
||||
|
||||
fDebugContextListener = new IDebugContextListener() {
|
||||
|
||||
@Override
|
||||
public void debugContextChanged(DebugContextEvent event) {
|
||||
|
||||
if ((event.getFlags() & DebugContextEvent.ACTIVATED) != 0) {
|
||||
ISelection s = event.getContext();
|
||||
setDebugContext(s);
|
||||
}
|
||||
}
|
||||
};
|
||||
contextService.addDebugContextListener(fDebugContextListener);
|
||||
setDebugContext(contextService.getActiveContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
super.dispose();
|
||||
|
||||
IDebugContextManager contextManager = DebugUITools.getDebugContextManager();
|
||||
IDebugContextService contextService = contextManager
|
||||
.getContextService(getSite().getWorkbenchWindow());
|
||||
contextService.removeDebugContextListener(fDebugContextListener);
|
||||
|
||||
setDebugContext((ICommandControlDMContext)null);
|
||||
DsfSession.removeSessionEndedListener(this);
|
||||
}
|
||||
|
||||
private void setDebugContext(ISelection s) {
|
||||
|
||||
ICommandControlDMContext context = null;
|
||||
fMultiple = false;
|
||||
if (s instanceof IStructuredSelection) {
|
||||
IStructuredSelection ss = (IStructuredSelection) s;
|
||||
if (ss.size() > 0) {
|
||||
@SuppressWarnings("rawtypes")
|
||||
Iterator i = ss.iterator();
|
||||
context = getCommandControlContext(i.next());
|
||||
while (i.hasNext()) {
|
||||
ICommandControlDMContext nextContext = getCommandControlContext(i.next());
|
||||
if (nextContext == null && context != null
|
||||
|| nextContext != null && context == null
|
||||
|| nextContext != null && context != null && !nextContext.equals(context))
|
||||
{
|
||||
context = null;
|
||||
fMultiple = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setDebugContext(context);
|
||||
}
|
||||
|
||||
private ICommandControlDMContext getCommandControlContext(Object obj) {
|
||||
IDMContext context = null;
|
||||
if (obj instanceof IDMVMContext)
|
||||
context = ((IDMVMContext)obj).getDMContext();
|
||||
else if (obj instanceof GdbLaunch) {
|
||||
GdbLaunch l = (GdbLaunch)obj;
|
||||
final DsfServicesTracker tracker = new DsfServicesTracker(GdbPlugin.getBundleContext(), l.getSession().getId());
|
||||
Query<IDMContext> contextQuery = new Query<IDMContext>() {
|
||||
@Override
|
||||
protected void execute(DataRequestMonitor<IDMContext> rm) {
|
||||
ICommandControlService commandControl = tracker.getService(ICommandControlService.class);
|
||||
tracker.dispose();
|
||||
if (commandControl != null)
|
||||
{
|
||||
rm.setData(commandControl.getContext());
|
||||
}
|
||||
rm.done();
|
||||
}
|
||||
};
|
||||
l.getSession().getExecutor().submit(contextQuery);
|
||||
try {
|
||||
context = contextQuery.get();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
return DMContexts.getAncestorOfType(context, ICommandControlDMContext.class);
|
||||
}
|
||||
|
||||
private void setDebugContext(ICommandControlDMContext context)
|
||||
{
|
||||
DsfSession newSession = null;
|
||||
SessionOSData newSessionData = null;
|
||||
|
||||
if (context != null)
|
||||
{
|
||||
newSession = DsfSession.getSession(context.getSessionId());
|
||||
}
|
||||
|
||||
if (newSession != null)
|
||||
{
|
||||
newSessionData = fSessionDataCache.get(newSession.getId());
|
||||
if (newSessionData == null)
|
||||
{
|
||||
newSessionData = new SessionOSData(newSession, context);
|
||||
fSessionDataCache.put(newSession.getId(), newSessionData);
|
||||
|
||||
newSessionData.setUIListener(new SessionOSData.Listener() {
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
// Note that fSessionData always calls the listener in
|
||||
// UI thread, so we can directly call 'update' here.
|
||||
OSResourcesView.this.update();
|
||||
}
|
||||
}, fViewer.getControl());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (newSessionData != fSessionData)
|
||||
{
|
||||
fSessionData = newSessionData;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sessionEnded(DsfSession session) {
|
||||
String id = session.getId();
|
||||
SessionOSData data = fSessionDataCache.remove(id);
|
||||
if (data != null) {
|
||||
data.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private void update() {
|
||||
|
||||
if (fViewer == null || fViewer.getControl() == null)
|
||||
return;
|
||||
|
||||
if (fViewer.getControl().isDisposed())
|
||||
return;
|
||||
|
||||
if (fSessionData == null)
|
||||
{
|
||||
hideTable(fMultiple ? Messages.OSView_14 : Messages.OSView_4);
|
||||
fResourceClassEditor.setEnabled(false);
|
||||
fRefreshAction.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
boolean enable = fSessionData.canFetchData();
|
||||
fRefreshAction.setEnabled(enable);
|
||||
fResourceClass = fResourceClassEditor.updateClasses(fSessionData.getResourceClasses());
|
||||
fResourceClassEditor.setEnabled(enable);
|
||||
|
||||
if (!fSessionData.osResourcesSupported()) {
|
||||
fRefreshAction.setEnabled(false);
|
||||
fResourceClassEditor.setEnabled(false);
|
||||
hideTable(Messages.OSView_10);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fSessionData.waitingForSessionInitialization()) {
|
||||
fRefreshAction.setEnabled(false);
|
||||
fResourceClassEditor.setEnabled(false);
|
||||
hideTable(Messages.OSView_13);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fSessionData.fetchingClasses()) {
|
||||
fRefreshAction.setEnabled(false);
|
||||
fResourceClassEditor.setEnabled(false);
|
||||
hideTable(Messages.OSView_11);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fResourceClass == null)
|
||||
{
|
||||
fRefreshAction.setEnabled(false);
|
||||
fResourceClassEditor.setEnabled(true);
|
||||
hideTable(Messages.OSView_5);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
final OSData data = fSessionData.existingData(fResourceClass);
|
||||
|
||||
if (fSessionData.fetchingContent())
|
||||
{
|
||||
hideTable(Messages.OSView_6);
|
||||
}
|
||||
else if (data == null)
|
||||
{
|
||||
if (fSessionData.canFetchData())
|
||||
hideTable(NLS.bind(Messages.OSView_7, FETCH_LINK_TAG));
|
||||
else
|
||||
hideTable(Messages.OSView_12);
|
||||
}
|
||||
else
|
||||
{
|
||||
SimpleDateFormat format = new SimpleDateFormat(Messages.OSView_8);
|
||||
fRefreshAction.setToolTipText(format.format(fSessionData.timestamp(fResourceClass)));
|
||||
if (data != fTableShownData)
|
||||
{
|
||||
Job job = new UIJob(Messages.OSView_9) {
|
||||
@Override
|
||||
public IStatus runInUIThread(IProgressMonitor monitor) {
|
||||
fTableShownData = data;
|
||||
populateTable(data);
|
||||
showTable();
|
||||
return Status.OK_STATUS;
|
||||
}
|
||||
|
||||
};
|
||||
job.setPriority(Job.INTERACTIVE);
|
||||
job.schedule();
|
||||
}
|
||||
else
|
||||
{
|
||||
assert fViewer.getTable().getColumnCount() == data.getColumnCount();
|
||||
showTable();
|
||||
}
|
||||
}
|
||||
fRefreshAction.setEnabled(fSessionData.canFetchData());
|
||||
fResourceClassEditor.setEnabled(fSessionData.canFetchData());
|
||||
|
||||
}
|
||||
|
||||
/* Hide the table that would show OS awareness data if it were available. Display
|
||||
* 'message' instead.
|
||||
*/
|
||||
private void hideTable(String message) {
|
||||
setContentDescription(""); //$NON-NLS-1$
|
||||
fViewer.getControl().setVisible(false);
|
||||
((GridData) fViewer.getControl().getLayoutData()).exclude = true;
|
||||
fNothingLabelContainer.setVisible(true);
|
||||
((GridData) fNothingLabelContainer.getLayoutData()).exclude = false;
|
||||
fNothingLabelContainer.getParent().layout();
|
||||
fNothingLabel.setText(message);
|
||||
fNothingLabelContainer.layout();
|
||||
|
||||
// If the table is not shown, we don't want the menu to have stale
|
||||
// list of columns to select from.
|
||||
IActionBars bars = getViewSite().getActionBars();
|
||||
bars.getMenuManager().removeAll();
|
||||
bars.updateActionBars();
|
||||
fMenuShownData = null;
|
||||
}
|
||||
|
||||
private void showTable() {
|
||||
assert fTableShownData != null;
|
||||
|
||||
fViewer.getControl().setVisible(true);
|
||||
((GridData) fViewer.getControl().getLayoutData()).exclude = false;
|
||||
fNothingLabelContainer.setVisible(false);
|
||||
((GridData) fNothingLabelContainer.getLayoutData()).exclude = true;
|
||||
fNothingLabelContainer.getParent().layout();
|
||||
|
||||
populateViewMenu(fTableShownData);
|
||||
}
|
||||
|
||||
private void populateTable(final OSData data)
|
||||
{
|
||||
final Table table = fViewer.getTable();
|
||||
|
||||
while (table.getColumnCount() > 0)
|
||||
table.getColumns()[0].dispose();
|
||||
|
||||
fColumnLayout = fColumnLayouts.get(fResourceClass);
|
||||
if (fColumnLayout == null)
|
||||
{
|
||||
fColumnLayout = new ColumnLayout(fResourceClass);
|
||||
fColumnLayouts.put(fResourceClass, fColumnLayout);
|
||||
}
|
||||
|
||||
for (int i = 0; i < data.getColumnCount(); ++i) {
|
||||
final String cn = data.getColumnName(i);
|
||||
final TableColumn c = new TableColumn(table, SWT.LEFT);
|
||||
c.setText(cn);
|
||||
|
||||
c.addListener(SWT.Resize, new Listener() {
|
||||
|
||||
@Override
|
||||
public void handleEvent(Event event) {
|
||||
fColumnLayout.setWidth(cn, c.getWidth());
|
||||
}
|
||||
});
|
||||
|
||||
final int final_index = i;
|
||||
c.addSelectionListener(new SelectionAdapter() {
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
int dir = table.getSortDirection();
|
||||
if (table.getSortColumn() == c) {
|
||||
dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
|
||||
} else {
|
||||
dir = SWT.DOWN;
|
||||
}
|
||||
table.setSortDirection(dir);
|
||||
table.setSortColumn(c);
|
||||
fComparator.configure(final_index, data);
|
||||
fComparator.setDirection(dir == SWT.DOWN ? 1 : -1);
|
||||
fColumnLayout.setSortColumn(final_index);
|
||||
fColumnLayout.setSortDirection(dir == SWT.DOWN ? 1 : -1);
|
||||
fViewer.refresh();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
populateViewMenu(data);
|
||||
|
||||
int sortColumn = fColumnLayout.getSortColumn();
|
||||
if (sortColumn < data.getColumnCount())
|
||||
{
|
||||
fComparator.configure(sortColumn, data);
|
||||
}
|
||||
fComparator.setDirection(fColumnLayout.getSortDirection());
|
||||
|
||||
fViewer.getTable().setEnabled(true);
|
||||
|
||||
|
||||
if (fViewer.getContentProvider() == null)
|
||||
{
|
||||
ContentLabelProviderWrapper<OSData> wrapper =
|
||||
new ContentLabelProviderWrapper<OSData>(data);
|
||||
fViewer.setContentProvider(wrapper);
|
||||
fViewer.setLabelProvider(wrapper);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Retarget current content/label providers in atomic fashion. See comments
|
||||
// on ContentLabelProviderWrapper.
|
||||
@SuppressWarnings("unchecked")
|
||||
ContentLabelProviderWrapper<OSData> wrapper = (ContentLabelProviderWrapper<OSData>)fViewer.getContentProvider();
|
||||
wrapper.setData(data);
|
||||
}
|
||||
fViewer.setInput(getViewSite());
|
||||
fViewer.getControl().setVisible(true);
|
||||
|
||||
for (int i = 0; i < fViewer.getTable().getColumnCount(); ++i)
|
||||
{
|
||||
TableColumn col = fViewer.getTable().getColumns()[i];
|
||||
String cn = col.getText();
|
||||
|
||||
if (i == sortColumn) {
|
||||
table.setSortDirection(fColumnLayout.getSortDirection() == 1 ? SWT.DOWN : SWT.UP);
|
||||
table.setSortColumn(col);
|
||||
}
|
||||
|
||||
if (fColumnLayout.getVisible(cn))
|
||||
{
|
||||
int w = fColumnLayout.getWidth(cn);
|
||||
if (w > 0)
|
||||
col.setWidth(w);
|
||||
else
|
||||
col.pack();
|
||||
}
|
||||
else
|
||||
{
|
||||
col.setWidth(0);
|
||||
col.setResizable(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void populateViewMenu(final OSData data) {
|
||||
|
||||
assert data.getColumnCount() == fViewer.getTable().getColumnCount();
|
||||
|
||||
if (data == fMenuShownData)
|
||||
return;
|
||||
|
||||
IActionBars bars = getViewSite().getActionBars();
|
||||
bars.getMenuManager().setVisible(true);
|
||||
bars.getMenuManager().removeAll();
|
||||
|
||||
for (int i = 0; i < data.getColumnCount(); ++i) {
|
||||
final String cn = data.getColumnName(i);
|
||||
final TableColumn c = fViewer.getTable().getColumns()[i];
|
||||
|
||||
Action a = new Action(cn, IAction.AS_CHECK_BOX) {
|
||||
@Override
|
||||
public void run() {
|
||||
if (isChecked()) {
|
||||
int w = fColumnLayout.getWidth(cn);
|
||||
if (w > 0)
|
||||
c.setWidth(w);
|
||||
else
|
||||
c.pack();
|
||||
c.setResizable(true);
|
||||
} else {
|
||||
int w = c.getWidth();
|
||||
c.setWidth(0);
|
||||
// Make sure we remember the width the column
|
||||
// had before hiding.
|
||||
fColumnLayout.setWidth(cn, w);
|
||||
c.setResizable(false);
|
||||
}
|
||||
fColumnLayout.setVisible(cn, isChecked());
|
||||
}
|
||||
};
|
||||
a.setChecked(fColumnLayout.getVisible(cn));
|
||||
a.setText(cn);
|
||||
bars.getMenuManager().add(a);
|
||||
}
|
||||
bars.updateActionBars();
|
||||
|
||||
fMenuShownData = data;
|
||||
}
|
||||
|
||||
class Comparator extends ViewerComparator
|
||||
{
|
||||
private int fColumn = 0;
|
||||
private OSData fData;
|
||||
private boolean fInteger = false;
|
||||
private int fDirection = 1;
|
||||
|
||||
public void configure(int column, OSData data)
|
||||
{
|
||||
fColumn = column;
|
||||
fData = data;
|
||||
fInteger = data.getColumnIsInteger(column);
|
||||
}
|
||||
|
||||
public void setDirection(int direction)
|
||||
{
|
||||
assert direction == 1 || direction == -1;
|
||||
fDirection = direction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(Viewer viewer, Object xe1, Object xe2) {
|
||||
|
||||
String v1 = fData.getColumnText(xe1, fColumn);
|
||||
String v2 = fData.getColumnText(xe2, fColumn);
|
||||
if (fInteger) {
|
||||
Integer i1 = Integer.parseInt(v1);
|
||||
Integer i2 = Integer.parseInt(v2);
|
||||
return fDirection*(i1 - i2);
|
||||
} else {
|
||||
return fDirection*(v1.compareTo(v2));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void setFocus() {
|
||||
fViewer.getControl().setFocus();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,210 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011, 2012 Mentor Graphics 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:
|
||||
* Vladimir Prus (Mentor Graphics) - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.dsf.gdb.internal.ui.osview;
|
||||
|
||||
import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
|
||||
import org.eclipse.cdt.dsf.gdb.service.IGDBHardwareAndOS2.IResourceClass;
|
||||
import org.eclipse.jface.action.ContributionItem;
|
||||
import org.eclipse.jface.dialogs.IDialogSettings;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.events.SelectionEvent;
|
||||
import org.eclipse.swt.events.SelectionListener;
|
||||
import org.eclipse.swt.graphics.GC;
|
||||
import org.eclipse.swt.widgets.Combo;
|
||||
import org.eclipse.swt.widgets.ToolBar;
|
||||
import org.eclipse.swt.widgets.ToolItem;
|
||||
|
||||
/**
|
||||
* @since 2.4
|
||||
*/
|
||||
public class ResourceClassContributionItem extends ContributionItem {
|
||||
|
||||
// In some places below, we are trying to determine size hint for Combo, given the list of
|
||||
// content. However, while we can determine width of content, we don't know how much width
|
||||
// the combobox itself is adding. This constant is our guess.
|
||||
private static final int COMBO_TRIM_WIDTH = 64;
|
||||
|
||||
interface Listener
|
||||
{
|
||||
void resourceClassChanged(String newClass);
|
||||
}
|
||||
|
||||
private Combo fResourceClassCombo;
|
||||
private IResourceClass[] resourceClasses = new IResourceClass[0];
|
||||
private String fResourceClassId = null;
|
||||
|
||||
private Listener fListener;
|
||||
private boolean blockListener = false;
|
||||
private ToolItem toolItem;
|
||||
|
||||
private boolean enabled = true;
|
||||
|
||||
private static IDialogSettings settings;
|
||||
private static IDialogSettings getDialogSettings()
|
||||
{
|
||||
if (settings != null)
|
||||
return settings;
|
||||
|
||||
IDialogSettings topSettings = GdbUIPlugin.getDefault().getDialogSettings();
|
||||
settings = topSettings.getSection(ResourceClassContributionItem.class.getName());
|
||||
if (settings == null) {
|
||||
settings = topSettings.addNewSection(ResourceClassContributionItem.class.getName());
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
|
||||
public void setListener(Listener listener) {
|
||||
|
||||
fListener = listener;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enable) {
|
||||
// It appears that every update of action bars will call 'fill' action below, creating
|
||||
// combo. So, we want to keep 'enabled' state as member variable, to make sure it is kept
|
||||
// if combo is recreated.
|
||||
enabled = enable;
|
||||
if (fResourceClassCombo != null)
|
||||
fResourceClassCombo.setEnabled(enable);
|
||||
}
|
||||
|
||||
public String updateClasses(IResourceClass[] resourceClasses) {
|
||||
|
||||
boolean different = false;
|
||||
if (this.resourceClasses.length != resourceClasses.length)
|
||||
different = true;
|
||||
else for (int i = 0; i < this.resourceClasses.length; ++i) {
|
||||
if (!this.resourceClasses[i].getId().equals(resourceClasses[i].getId())
|
||||
|| !this.resourceClasses[i].getHumanDescription().equals(resourceClasses[i].getHumanDescription()))
|
||||
{
|
||||
different = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!different)
|
||||
return fResourceClassId;
|
||||
|
||||
this.resourceClasses = resourceClasses;
|
||||
|
||||
fResourceClassCombo.removeAll();
|
||||
final int width = populateCombo();
|
||||
// Now change the width. Call to setWidth causes relayout automatically.
|
||||
// IMPORTANT: the visibility check is critical. Without it, we appear to have hit
|
||||
// an SWT/Gtk bug whenever a debug session and a previously use OS resources view
|
||||
// is not shown. The bug manifests by 100% CPU consumption inside event loop, and
|
||||
// it further blocks asyncExec runnables from ever executing. I suppose it might
|
||||
// be specific to relayout of invisible toolbar.
|
||||
|
||||
// If we're invisible, we don't arrange for relayout to happen when the view becomes
|
||||
// available, because it is not exactly trivial (we need to events on the right control)
|
||||
// and it only matters when we start a new session and it has a different set of
|
||||
// resource classes and that requires longer combobox.
|
||||
if (toolItem.getParent().isVisible())
|
||||
toolItem.setWidth(width);
|
||||
|
||||
return fResourceClassId;
|
||||
}
|
||||
|
||||
/** Populate the combobox with resource classes. Return the width the
|
||||
* combobox must have, including any trim. If there are no resource classes,
|
||||
* returns some reasonable default width.
|
||||
*/
|
||||
private int populateCombo() {
|
||||
|
||||
int width = 0;
|
||||
String lastResourceClassId = getDialogSettings().get("resourceClass"); //$NON-NLS-1$
|
||||
int index = -1;
|
||||
int i = 0;
|
||||
GC gc = new GC(fResourceClassCombo);
|
||||
for (i = 0; i < resourceClasses.length; ++i) {
|
||||
String description = resourceClasses[i].getHumanDescription();
|
||||
width = Math.max(width, gc.textExtent(description).x);
|
||||
fResourceClassCombo.add(description);
|
||||
if (resourceClasses[i].getId().equals(lastResourceClassId))
|
||||
index = i;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (index != -1) {
|
||||
fResourceClassId = lastResourceClassId;
|
||||
blockListener = true;
|
||||
fResourceClassCombo.select(index);
|
||||
blockListener = false;
|
||||
}
|
||||
|
||||
if (width == 0) {
|
||||
// We have some hints what the longest element in combo will be. Even if it's different
|
||||
// in new GDB version, no problem -- the combo will be resized when it's populated.
|
||||
width = gc.textExtent("Shared memory regions").x; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
// Because there's no way whatsoever to set the width
|
||||
// of the combobox list, only complete length, we just add
|
||||
// random padding.
|
||||
width = width + COMBO_TRIM_WIDTH;
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
|
||||
public String getResourceClassId() {
|
||||
return fResourceClassId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fill(ToolBar parent, int toolbarItemIndex) {
|
||||
|
||||
fResourceClassCombo = new Combo(parent, SWT.NONE);
|
||||
fResourceClassCombo.setEnabled(enabled);
|
||||
int width = populateCombo();
|
||||
|
||||
fResourceClassCombo.addSelectionListener(new SelectionListener() {
|
||||
|
||||
@SuppressWarnings({ "null"})
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
String description = fResourceClassCombo.getText();
|
||||
String id = null;
|
||||
for (int i = 0; i < resourceClasses.length; ++i)
|
||||
if (resourceClasses[i].getHumanDescription().equals(description)) {
|
||||
id = resourceClasses[i].getId();
|
||||
break;
|
||||
}
|
||||
|
||||
// id is never null here, unless we messed up our data structures.
|
||||
assert id != null;
|
||||
if (id != null && !id.equals(fResourceClassId))
|
||||
{
|
||||
fResourceClassId = id;
|
||||
getDialogSettings().put("resourceClass", id); //$NON-NLS-1$
|
||||
if (fListener != null && !blockListener)
|
||||
fListener.resourceClassChanged(fResourceClassId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void widgetDefaultSelected(SelectionEvent e) {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
toolItem = new ToolItem(parent, SWT.SEPARATOR);
|
||||
toolItem.setControl(fResourceClassCombo);
|
||||
toolItem.setWidth(width);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDynamic() {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,292 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011, 2012 Mentor Graphics 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:
|
||||
* Vladimir Prus (Mentor Graphics) - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.dsf.gdb.internal.ui.osview;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor;
|
||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
|
||||
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
|
||||
import org.eclipse.cdt.dsf.datamodel.DataModelInitializedEvent;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerResumedDMEvent;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerSuspendedDMEvent;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IResumedDMEvent;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
|
||||
import org.eclipse.cdt.dsf.gdb.service.IGDBHardwareAndOS2;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIRunControl;
|
||||
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
|
||||
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
|
||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||
import org.eclipse.swt.widgets.Control;
|
||||
import org.eclipse.swt.widgets.Display;
|
||||
import org.eclipse.ui.statushandlers.StatusManager;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
||||
/** Responsible for fetching and storing OS awareness data for a
|
||||
* specific DSF session.
|
||||
*
|
||||
* @since 2.4
|
||||
*/
|
||||
public class SessionOSData {
|
||||
|
||||
private DsfSession fSession;
|
||||
private DsfServicesTracker fTracker;
|
||||
private IGDBHardwareAndOS2 fHardwareOs;
|
||||
private ICommandControlDMContext fContext;
|
||||
|
||||
private IGDBHardwareAndOS2.IResourceClass[] fResourceClasses = new IGDBHardwareAndOS2.IResourceClass[0];
|
||||
private Map<String, OSData> fExistingData = new HashMap<String, OSData>();
|
||||
private Map<String, Date> fTimestamp = new HashMap<String, Date>();
|
||||
|
||||
private Listener fUIListener;
|
||||
private Control fUIControl;
|
||||
|
||||
private boolean fWaitingForSession = true;
|
||||
private boolean fSupported = true;
|
||||
private boolean fAcceptingCommands = false;
|
||||
private boolean fFetchingClasses = false;
|
||||
private boolean fFetchingContent = false;
|
||||
|
||||
|
||||
public SessionOSData(DsfSession session, final ICommandControlDMContext executionContext)
|
||||
{
|
||||
fSession = session;
|
||||
BundleContext c = GdbUIPlugin.getDefault().getBundle().getBundleContext();
|
||||
fTracker = new DsfServicesTracker(c, fSession.getId());
|
||||
fContext = executionContext;
|
||||
|
||||
final DsfExecutor executor = fSession.getExecutor();
|
||||
executor.submit(new DsfRunnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
IMIRunControl runControl = fTracker.getService(IMIRunControl.class);
|
||||
fAcceptingCommands = runControl.isTargetAcceptingCommands();
|
||||
|
||||
fSession.addServiceEventListener(SessionOSData.this, null);
|
||||
|
||||
fHardwareOs = fTracker.getService(IGDBHardwareAndOS2.class);
|
||||
|
||||
if (fHardwareOs == null) {
|
||||
fSupported = false;
|
||||
notifyUI();
|
||||
return;
|
||||
}
|
||||
|
||||
if (fHardwareOs.isAvailable()) {
|
||||
fetchClasses();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ConfinedToDsfExecutor("")
|
||||
private void fetchClasses()
|
||||
{
|
||||
fWaitingForSession = false;
|
||||
fFetchingClasses = true;
|
||||
fHardwareOs.getResourceClasses(fContext, new DataRequestMonitor<IGDBHardwareAndOS2.IResourceClass[]>(fSession.getExecutor(), null) {
|
||||
@Override
|
||||
@ConfinedToDsfExecutor("fExecutor")
|
||||
protected void handleCompleted() {
|
||||
|
||||
if (isSuccess())
|
||||
{
|
||||
fResourceClasses = getData();
|
||||
if (fResourceClasses.length == 0)
|
||||
fSupported = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
fSupported = false;
|
||||
}
|
||||
fFetchingClasses = false;
|
||||
notifyUI();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@DsfServiceEventHandler
|
||||
public void eventDispatched(DataModelInitializedEvent e) {
|
||||
// If we see this event, it necessary means that by the time we've set event listener,
|
||||
// isAvailable() was returning false, so we need to fetch classes now.
|
||||
if (fHardwareOs != null)
|
||||
fetchClasses();
|
||||
}
|
||||
|
||||
public boolean waitingForSessionInitialization()
|
||||
{
|
||||
return fWaitingForSession;
|
||||
}
|
||||
|
||||
public boolean osResourcesSupported()
|
||||
{
|
||||
return fSupported;
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
fSession.removeServiceEventListener(SessionOSData.this);
|
||||
fTracker.dispose();
|
||||
}
|
||||
|
||||
public IGDBHardwareAndOS2.IResourceClass[] getResourceClasses()
|
||||
{
|
||||
return fResourceClasses;
|
||||
}
|
||||
|
||||
/** Returns OS awareness data for given resource class that
|
||||
* was previously fetched, or null if none was ever fetched.
|
||||
*/
|
||||
public OSData existingData(String resourceClass)
|
||||
{
|
||||
return fExistingData.get(resourceClass);
|
||||
}
|
||||
|
||||
/** Returns the timestamp at which data for 'resourceClass' have
|
||||
* been obtained.
|
||||
* @pre existingData(resourceClass) != null
|
||||
*/
|
||||
public Date timestamp(String resourceClass)
|
||||
{
|
||||
return fTimestamp.get(resourceClass);
|
||||
}
|
||||
|
||||
/** Returns true if fresh data can be fetched at this time.
|
||||
* Generally, it's possible if we're not fetching data already,
|
||||
* and if GDB is accepting commands right now.
|
||||
*
|
||||
*/
|
||||
public boolean canFetchData()
|
||||
{
|
||||
return fAcceptingCommands && !fFetchingContent;
|
||||
}
|
||||
|
||||
public boolean fetchingClasses()
|
||||
{
|
||||
return fFetchingClasses;
|
||||
}
|
||||
|
||||
/** Returns true if we're presently fetching data. This can
|
||||
* be used to provide some feedback to the user.
|
||||
*/
|
||||
public boolean fetchingContent()
|
||||
{
|
||||
return fFetchingContent;
|
||||
}
|
||||
|
||||
/** Fetches up-to-date data for resourceClass. Listeners will be
|
||||
* informed when the new data is available. */
|
||||
public void fetchData(final String resourceClass)
|
||||
{
|
||||
fFetchingContent = true;
|
||||
notifyUI();
|
||||
|
||||
final DsfExecutor executor = fSession.getExecutor();
|
||||
executor.submit(new DsfRunnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
fHardwareOs.getResourcesInformation(fContext, resourceClass, new DataRequestMonitor<IGDBHardwareAndOS2.IResourcesInformation>(executor, null) {
|
||||
|
||||
@Override
|
||||
@ConfinedToDsfExecutor("fExecutor")
|
||||
protected void handleCompleted() {
|
||||
|
||||
fFetchingContent = false;
|
||||
|
||||
if (isSuccess())
|
||||
{
|
||||
OSData data = new OSData(resourceClass, getData());
|
||||
fExistingData.put(resourceClass, data);
|
||||
fTimestamp.put(resourceClass, new Date());
|
||||
}
|
||||
else
|
||||
{
|
||||
StatusManager.getManager().handle(getStatus(), StatusManager.BLOCK);
|
||||
}
|
||||
notifyUI();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
public interface Listener
|
||||
{
|
||||
void update();
|
||||
}
|
||||
|
||||
/** Setup the listener that will be notified whenever externally
|
||||
* visible state changes. The listener will always be invoked
|
||||
* in the UI thread. 'control' is the control associated with
|
||||
* the listener. The listener will not be called if the control
|
||||
* is disposed.
|
||||
*/
|
||||
public void setUIListener(Listener listener, Control control)
|
||||
{
|
||||
fUIListener = listener;
|
||||
fUIControl = control;
|
||||
}
|
||||
|
||||
private void notifyUI()
|
||||
{
|
||||
|
||||
final Control c = fUIControl;
|
||||
if (c != null && !c.isDisposed())
|
||||
// There be dragons: if you try to use c.getDisplay() below, then this Runnable will not
|
||||
// run until resource view is actually visible. And it will also block other interesting
|
||||
// async/job runnables, like perspective switch runnable using during debug launch,
|
||||
// causing launch to be stuck at random point.
|
||||
//
|
||||
Display.getDefault().asyncExec(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
if (!c.isDisposed())
|
||||
fUIListener.update();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@DsfServiceEventHandler
|
||||
public void eventDispatched(IResumedDMEvent e) {
|
||||
if (e instanceof IContainerResumedDMEvent) {
|
||||
// This event is raised only in all-stop. It does not
|
||||
// seem to be possible to issue -info-os in all-stop,
|
||||
// regardless of whether target-async is in effect, and
|
||||
// according to DSF folks, all-stop+target-async will
|
||||
// not work anyway. So, we assume that no commands
|
||||
// can be issued right now.
|
||||
fAcceptingCommands = false;
|
||||
notifyUI();
|
||||
}
|
||||
}
|
||||
|
||||
@DsfServiceEventHandler
|
||||
public void eventDispatched(ISuspendedDMEvent e) {
|
||||
if (e instanceof IContainerSuspendedDMEvent) {
|
||||
fAcceptingCommands = true;
|
||||
notifyUI();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011, 2012 Mentor Graphics 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:
|
||||
* Vladimir Prus (Mentor Graphics) - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.dsf.gdb.service;
|
||||
|
||||
import java.util.Hashtable;
|
||||
|
||||
import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor;
|
||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfoOsInfo;
|
||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
|
||||
/**
|
||||
* @since 4.2
|
||||
*/
|
||||
public class GDBHardwareAndOS_7_5 extends GDBHardwareAndOS implements IGDBHardwareAndOS2 {
|
||||
|
||||
public GDBHardwareAndOS_7_5(DsfSession session) {
|
||||
super(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return getSessionInitializationComplete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(final RequestMonitor requestMonitor) {
|
||||
super.initialize(new RequestMonitor(ImmediateExecutor.getInstance(), requestMonitor) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
register(new String[] { IGDBHardwareAndOS2.class.getName() },
|
||||
new Hashtable<String, String>());
|
||||
|
||||
requestMonitor.done();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getResourceClasses(final IDMContext dmc, final DataRequestMonitor<IResourceClass[]> rm) {
|
||||
|
||||
IGDBControl control = getServicesTracker().getService(IGDBControl.class);
|
||||
if (control == null) {
|
||||
rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Service not available", null)); //$NON-NLS-1$
|
||||
return;
|
||||
}
|
||||
|
||||
CommandFactory factory = control.getCommandFactory();
|
||||
control.queueCommand(factory.createMIInfoOS(dmc), new DataRequestMonitor<MIInfoOsInfo>(getExecutor(), rm) {
|
||||
@Override
|
||||
@ConfinedToDsfExecutor("fExecutor")
|
||||
protected void handleSuccess() {
|
||||
rm.setData(getData().getResourceClasses());
|
||||
rm.done();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getResourcesInformation(final IDMContext dmc, final String resourceClass, final DataRequestMonitor<IResourcesInformation> rm) {
|
||||
|
||||
IGDBControl control = getServicesTracker().getService(IGDBControl.class);
|
||||
if (control == null) {
|
||||
rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Service not available", null)); //$NON-NLS-1$
|
||||
return;
|
||||
}
|
||||
|
||||
CommandFactory factory = control.getCommandFactory();
|
||||
control.queueCommand(factory.createMIInfoOS(dmc, resourceClass), new DataRequestMonitor<MIInfoOsInfo>(getExecutor(), rm) {
|
||||
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
rm.setData(getData().getResourcesInformation());
|
||||
rm.done();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -11,6 +11,7 @@
|
|||
* Onur Akdemir (TUBITAK BILGEM-ITI) - Multi-process debugging (Bug 237306)
|
||||
* Marc Khouzam (Ericsson) - Support for GDB 7.4 (Bug 367788)
|
||||
* Marc Khouzam (Ericsson) - Include IGDBHardware service for the multicore visualizer (Bug 335027)
|
||||
* Vladimir Prus (Mentor Graphics) - Support for OS resources.
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.dsf.gdb.service;
|
||||
|
||||
|
@ -62,6 +63,8 @@ public class GdbDebugServicesFactory extends AbstractDsfDebugServicesFactory {
|
|||
public static final String GDB_7_3_VERSION = "7.3"; //$NON-NLS-1$
|
||||
/** @since 4.1 */
|
||||
public static final String GDB_7_4_VERSION = "7.4"; //$NON-NLS-1$
|
||||
/** @since 4.2*/
|
||||
public static final String GDB_7_5_VERSION = "7.5"; //$NON-NLS-1$
|
||||
|
||||
private final String fVersion;
|
||||
|
||||
|
@ -229,6 +232,9 @@ public class GdbDebugServicesFactory extends AbstractDsfDebugServicesFactory {
|
|||
|
||||
/** @since 4.1 */
|
||||
protected IGDBHardwareAndOS createHardwareAndOSService(DsfSession session, ILaunchConfiguration config) {
|
||||
if (GDB_7_5_VERSION.compareTo(fVersion) <= 0) {
|
||||
return new GDBHardwareAndOS_7_5(session);
|
||||
}
|
||||
return new GDBHardwareAndOS(session);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011, 2012 Mentor Graphics 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:
|
||||
* Vladimir Prus (Mentor Graphics) - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.dsf.gdb.service;
|
||||
|
||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||
|
||||
/**
|
||||
* Interface for accessing information about OS resources.
|
||||
*
|
||||
* <strong>EXPERIMENTAL</strong>. This class or interface has been added as part
|
||||
* of a work in progress. There is no guarantee that this API will work or that
|
||||
* it will remain the same.
|
||||
*
|
||||
* @since 4.2
|
||||
*/
|
||||
public interface IGDBHardwareAndOS2 extends IGDBHardwareAndOS {
|
||||
|
||||
/** Returns true if information returned by the other methods is available.
|
||||
* If false is returned, it means that session initialization is in progress,
|
||||
* and further request should be made after DataModelInitializedEvent is fired.
|
||||
*/
|
||||
public boolean isAvailable();
|
||||
|
||||
/** Information about OS resource class. */
|
||||
public interface IResourceClass
|
||||
{
|
||||
/** The id of this resource class, used in GDB requests. */
|
||||
public String getId();
|
||||
/** Human-friendly description of this class, suitable for direct display in UI. */
|
||||
public String getHumanDescription();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of OS resource classes GDB knows about
|
||||
*/
|
||||
public void getResourceClasses(IDMContext dmc, DataRequestMonitor<IResourceClass[]> rm);
|
||||
|
||||
/** Information about OS resources of specific resource class
|
||||
* This is conceptually a table. GDB provides column headers, and
|
||||
* data rows, but does not provide any additional information about
|
||||
* the meaning
|
||||
*/
|
||||
public interface IResourcesInformation
|
||||
{
|
||||
/** Return the names of the columns in resource table. */
|
||||
public String[] getColumnNames();
|
||||
/** Returns rows of the resource table. Each element is an array
|
||||
* of the size equal to getColumnNames().length
|
||||
*/
|
||||
public String[][] getContent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return table describing resources of specified class.
|
||||
*/
|
||||
void getResourcesInformation(IDMContext dmc, String resourceClassId, DataRequestMonitor<IResourcesInformation> rm);
|
||||
}
|
|
@ -18,6 +18,7 @@
|
|||
* Marc Khouzam (Ericsson) - New method for new MIGDBSetPythonPrintStack (Bug 367788)
|
||||
* Mathias Kunter - New methods for handling different charsets (Bug 370462)
|
||||
* Anton Gorenkov - A preference to use RTTI for variable types determination (Bug 377536)
|
||||
* Vladimir Prus (Mentor Graphics) - Support for -info-os (Bug 360314)
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.dsf.mi.service.command;
|
||||
|
@ -118,6 +119,7 @@ import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSetTargetCharset;
|
|||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSetTargetWideCharset;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBShowExitCode;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIInferiorTTYSet;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIInfoOs;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIInterpreterExec;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIInterpreterExecConsole;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIInterpreterExecConsoleKill;
|
||||
|
@ -181,6 +183,7 @@ import org.eclipse.cdt.dsf.mi.service.command.output.MIDataReadMemoryInfo;
|
|||
import org.eclipse.cdt.dsf.mi.service.command.output.MIDataWriteMemoryInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIGDBShowExitCodeInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfoOsInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIListFeaturesInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIListThreadGroupsInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIStackInfoDepthInfo;
|
||||
|
@ -708,6 +711,20 @@ public class CommandFactory {
|
|||
return new MIInferiorTTYSet(dmc, tty);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.2
|
||||
*/
|
||||
public ICommand<MIInfoOsInfo> createMIInfoOS(IDMContext ctx) {
|
||||
return new MIInfoOs(ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.2
|
||||
*/
|
||||
public ICommand<MIInfoOsInfo> createMIInfoOS(IDMContext ctx, String resourceClass) {
|
||||
return new MIInfoOs(ctx, resourceClass);
|
||||
}
|
||||
|
||||
public ICommand<MIInfo> createMIInterpreterExec(IDMContext ctx, String interpreter, String cmd) {
|
||||
return new MIInterpreterExec<MIInfo>(ctx, interpreter, cmd);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Mentor Graphics 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:
|
||||
* Vladimir Prus (Mentor Graphics) - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.dsf.mi.service.command.commands;
|
||||
|
||||
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MICommand;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfoOsInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIOutput;
|
||||
|
||||
/**
|
||||
* MIInfoOS
|
||||
*
|
||||
* -info-os [ type ]
|
||||
* If no argument is supplied, the command returns a table of
|
||||
* available operating-system-specific information types. If one of these
|
||||
* types is supplied as an argument type, then the command returns a
|
||||
* table of data of that type.
|
||||
*
|
||||
* The types of information available depend on the target operating system.
|
||||
* @since 4.2
|
||||
*/
|
||||
public class MIInfoOs extends MICommand<MIInfoOsInfo> {
|
||||
|
||||
public MIInfoOs(IDMContext ctx)
|
||||
{
|
||||
super(ctx, "-info-os"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
public MIInfoOs(IDMContext ctx, String resourceClass)
|
||||
{
|
||||
super(ctx, "-info-os", new String[]{resourceClass}); //$NON-NLS-1$
|
||||
specificResource = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MIInfoOsInfo getResult(MIOutput out) {
|
||||
|
||||
return new MIInfoOsInfo(out, specificResource);
|
||||
}
|
||||
|
||||
private boolean specificResource = false;
|
||||
|
||||
}
|
|
@ -0,0 +1,187 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011, 2012 Mentor Graphics 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:
|
||||
* Vladimir Prus (Mentor Graphics) - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.dsf.mi.service.command.output;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.cdt.dsf.gdb.service.IGDBHardwareAndOS2;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIOutput;
|
||||
|
||||
/**
|
||||
* Example output:
|
||||
*
|
||||
* (gdb) -info-os
|
||||
* ^done,OSDataTable={nr_rows="9",nr_cols="3",
|
||||
* hdr=[{width="10",alignment="-1",col_name="col0",colhdr="Type"},
|
||||
* {width="10",alignment="-1",col_name="col1",colhdr="Description"},
|
||||
* {width="10",alignment="-1",col_name="col2",colhdr="Title"}],
|
||||
* body=[item={col0="processes",col1="Listing of all processes",
|
||||
* col2="Processes"},
|
||||
* item={col0="procgroups",col1="Listing of all process groups",
|
||||
* col2="Process groups"},
|
||||
* item={col0="threads",col1="Listing of all threads",
|
||||
* col2="Threads"},
|
||||
* item={col0="files",col1="Listing of all file descriptors",
|
||||
* col2="File descriptors"},
|
||||
* item={col0="sockets",col1="Listing of all internet-domain sockets",
|
||||
* col2="Sockets"},
|
||||
* item={col0="shm",col1="Listing of all shared-memory regions",
|
||||
* col2="Shared-memory regions"},
|
||||
* item={col0="semaphores",col1="Listing of all semaphores",
|
||||
* col2="Semaphores"},
|
||||
* item={col0="msg",col1="Listing of all message queues",
|
||||
* col2="Message queues"},
|
||||
* item={col0="modules",col1="Listing of all loaded kernel modules",
|
||||
* col2="Kernel modules"}]}
|
||||
* (gdb) -info-os processes
|
||||
* ^done,OSDataTable={nr_rows="190",nr_cols="4",
|
||||
* hdr=[{width="10",alignment="-1",col_name="col0",colhdr="pid"},
|
||||
* {width="10",alignment="-1",col_name="col1",colhdr="user"},
|
||||
* {width="10",alignment="-1",col_name="col2",colhdr="command"},
|
||||
* {width="10",alignment="-1",col_name="col3",colhdr="cores"}],
|
||||
* body=[item={col0="1",col1="root",col2="/sbin/init",col3="0"},
|
||||
* item={col0="2",col1="root",col2="[kthreadd]",col3="1"},
|
||||
* item={col0="3",col1="root",col2="[ksoftirqd/0]",col3="0"},
|
||||
* ...
|
||||
* item={col0="26446",col1="stan",col2="bash",col3="0"},
|
||||
* item={col0="28152",col1="stan",col2="bash",col3="1"}]}
|
||||
* (gdb)
|
||||
*
|
||||
* @since 4.2
|
||||
*/
|
||||
public class MIInfoOsInfo extends MIInfo {
|
||||
|
||||
// The fields below are used for response with list of classes.
|
||||
private IGDBHardwareAndOS2.IResourceClass[] resourceClasses;
|
||||
|
||||
// The below fields are used only for data with specific resource class
|
||||
private String[] columnNames;
|
||||
private String[][] content;
|
||||
|
||||
public MIInfoOsInfo(MIOutput record, boolean resourcesInformation) {
|
||||
super(record);
|
||||
if (isDone()) {
|
||||
if (resourcesInformation)
|
||||
parseResourcesInformation();
|
||||
else
|
||||
parseResourceClasses();
|
||||
}
|
||||
}
|
||||
|
||||
public IGDBHardwareAndOS2.IResourcesInformation getResourcesInformation()
|
||||
{
|
||||
return new IGDBHardwareAndOS2.IResourcesInformation() {
|
||||
|
||||
@Override
|
||||
public String[][] getContent() { return content; }
|
||||
|
||||
@Override
|
||||
public String[] getColumnNames() { return columnNames; }
|
||||
};
|
||||
}
|
||||
|
||||
public IGDBHardwareAndOS2.IResourceClass[] getResourceClasses()
|
||||
{
|
||||
return resourceClasses;
|
||||
}
|
||||
|
||||
private void parseResourceClasses()
|
||||
{
|
||||
List<IGDBHardwareAndOS2.IResourceClass> classes = new ArrayList<IGDBHardwareAndOS2.IResourceClass>();
|
||||
|
||||
MITuple table = (MITuple)get(getMIOutput(), "OSDataTable"); //$NON-NLS-1$
|
||||
|
||||
MIList body = (MIList)get(table, "body"); //$NON-NLS-1$
|
||||
for (MIResult r: body.getMIResults()) {
|
||||
MITuple row = (MITuple)r.getMIValue();
|
||||
|
||||
final String id = getString(row.getMIResults()[0]);
|
||||
final String description = getString(row.getMIResults()[2]);
|
||||
|
||||
classes.add(new IGDBHardwareAndOS2.IResourceClass() {
|
||||
|
||||
@Override
|
||||
public String getId() { return id; }
|
||||
|
||||
@Override
|
||||
public String getHumanDescription() { return description; }
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
resourceClasses = classes.toArray(new IGDBHardwareAndOS2.IResourceClass[classes.size()]);
|
||||
}
|
||||
|
||||
private void parseResourcesInformation()
|
||||
{
|
||||
MITuple table = (MITuple) get(getMIOutput(), "OSDataTable"); //$NON-NLS-1$
|
||||
|
||||
MIList header = (MIList) get(table, "hdr"); //$NON-NLS-1$
|
||||
columnNames = new String[header.getMIValues().length];
|
||||
int i = 0;
|
||||
for (MIValue v : header.getMIValues()) {
|
||||
MITuple column = (MITuple) v;
|
||||
String columnName = ((MIConst) get(column, "colhdr")).getString(); //$NON-NLS-1$
|
||||
columnNames[i++] = Character.toUpperCase(columnName.charAt(0)) + columnName.substring(1);
|
||||
}
|
||||
|
||||
|
||||
MIList body = (MIList) get(table, "body"); //$NON-NLS-1$
|
||||
if (body == null)
|
||||
{
|
||||
content = new String[0][];
|
||||
return;
|
||||
}
|
||||
|
||||
content = new String[body.getMIResults().length][];
|
||||
i = 0;
|
||||
for (MIResult r : body.getMIResults()) {
|
||||
MITuple row = (MITuple) r.getMIValue();
|
||||
assert row.getMIResults().length == columnNames.length;
|
||||
String[] rowStrings = new String[row.getMIResults().length];
|
||||
int j = 0;
|
||||
for (MIResult r2 : row.getMIResults())
|
||||
{
|
||||
rowStrings[j] = ((MIConst) r2.getMIValue()).getString();
|
||||
++j;
|
||||
}
|
||||
content[i++] = rowStrings;
|
||||
}
|
||||
}
|
||||
|
||||
private MIValue get(MIResult[] results, String name) {
|
||||
for (MIResult r : results)
|
||||
if (r.getVariable().equals(name))
|
||||
return r.getMIValue();
|
||||
return null;
|
||||
}
|
||||
|
||||
private MIValue get(MIOutput output, String name) {
|
||||
return get(output.getMIResultRecord().getMIResults(), name);
|
||||
}
|
||||
|
||||
private MIValue get(MITuple tuple, String name) {
|
||||
return get(tuple.getMIResults(), name);
|
||||
}
|
||||
|
||||
private String getString(MIValue value)
|
||||
{
|
||||
return ((MIConst)value).getString();
|
||||
}
|
||||
|
||||
private String getString(MIResult result)
|
||||
{
|
||||
return getString(result.getMIValue());
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue