diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/META-INF/MANIFEST.MF b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/META-INF/MANIFEST.MF
index d4e6cc44ddc..8d3a7df5824 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/META-INF/MANIFEST.MF
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/META-INF/MANIFEST.MF
@@ -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,
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/view16/osresources_view.gif b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/view16/osresources_view.gif
new file mode 100644
index 00000000000..71fc0a4f941
Binary files /dev/null and b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/view16/osresources_view.gif differ
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.properties b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.properties
index 6248385f21a..219fa516a90 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.properties
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.properties
@@ -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
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.xml b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.xml
index b59f15537b5..81593486d9a 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.xml
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.xml
@@ -263,6 +263,13 @@
id="org.eclipse.cdt.dsf.gdb.ui.tracecontrol.view"
name="%view.traceControl.name">
+
+
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/pom.xml b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/pom.xml
index a418ced7299..16b88d43c30 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/pom.xml
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/pom.xml
@@ -11,7 +11,7 @@
../../pom.xml
- 2.3.0-SNAPSHOT
+ 2.4.0-SNAPSHOT
org.eclipse.cdt.dsf.gdb.ui
eclipse-plugin
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/osview/ColumnLayout.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/osview/ColumnLayout.java
new file mode 100644
index 00000000000..f8727623645
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/osview/ColumnLayout.java
@@ -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 fVisible = new HashMap();
+ private Map fWidth = new HashMap();
+ 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$
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/osview/ContentLabelProviderWrapper.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/osview/ContentLabelProviderWrapper.java
new file mode 100644
index 00000000000..d322b096fd7
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/osview/ContentLabelProviderWrapper.java
@@ -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
+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;
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/osview/Messages.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/osview/Messages.java
new file mode 100644
index 00000000000..ae708ab7f14
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/osview/Messages.java
@@ -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() {
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/osview/Messages.properties b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/osview/Messages.properties
new file mode 100644
index 00000000000..f57587aa280
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/osview/Messages.properties
@@ -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. Fetch now.
+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.
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/osview/OSData.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/osview/OSData.java
new file mode 100644
index 00000000000..0bbad09af74
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/osview/OSData.java
@@ -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 remap;
+
+ public OSData(String resourceClass, IResourcesInformation data) {
+ this.data = data;
+ determineColumnTypes();
+
+ remap = new ArrayList(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();
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/osview/OSResourcesView.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/osview/OSResourcesView.java
new file mode 100644
index 00000000000..5e5f2a7cc5a
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/osview/OSResourcesView.java
@@ -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 fSessionDataCache = new HashMap();
+ // 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 fColumnLayouts = new HashMap();
+
+ 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 contextQuery = new Query() {
+ @Override
+ protected void execute(DataRequestMonitor 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 wrapper =
+ new ContentLabelProviderWrapper(data);
+ fViewer.setContentProvider(wrapper);
+ fViewer.setLabelProvider(wrapper);
+ }
+ else
+ {
+ // Retarget current content/label providers in atomic fashion. See comments
+ // on ContentLabelProviderWrapper.
+ @SuppressWarnings("unchecked")
+ ContentLabelProviderWrapper wrapper = (ContentLabelProviderWrapper)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();
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/osview/ResourceClassContributionItem.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/osview/ResourceClassContributionItem.java
new file mode 100644
index 00000000000..68c37dfd91a
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/osview/ResourceClassContributionItem.java
@@ -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;
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/osview/SessionOSData.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/osview/SessionOSData.java
new file mode 100644
index 00000000000..bfcbed340ea
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/osview/SessionOSData.java
@@ -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 fExistingData = new HashMap();
+ private Map fTimestamp = new HashMap();
+
+ 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(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(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();
+ }
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBHardwareAndOS_7_5.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBHardwareAndOS_7_5.java
new file mode 100644
index 00000000000..537c321216a
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBHardwareAndOS_7_5.java
@@ -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());
+
+ requestMonitor.done();
+ }
+ });
+ }
+
+ @Override
+ public void getResourceClasses(final IDMContext dmc, final DataRequestMonitor 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(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 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(getExecutor(), rm) {
+
+ @Override
+ protected void handleSuccess() {
+ rm.setData(getData().getResourcesInformation());
+ rm.done();
+ }
+ });
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java
index 3d33d62131e..27501dff4ee 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java
@@ -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);
}
}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IGDBHardwareAndOS2.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IGDBHardwareAndOS2.java
new file mode 100644
index 00000000000..256c67dd93f
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IGDBHardwareAndOS2.java
@@ -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.
+ *
+ * EXPERIMENTAL. 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 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 rm);
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CommandFactory.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CommandFactory.java
index a706ee91c90..f62b44c1882 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CommandFactory.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CommandFactory.java
@@ -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 createMIInfoOS(IDMContext ctx) {
+ return new MIInfoOs(ctx);
+ }
+
+ /**
+ * @since 4.2
+ */
+ public ICommand createMIInfoOS(IDMContext ctx, String resourceClass) {
+ return new MIInfoOs(ctx, resourceClass);
+ }
+
public ICommand createMIInterpreterExec(IDMContext ctx, String interpreter, String cmd) {
return new MIInterpreterExec(ctx, interpreter, cmd);
}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIInfoOs.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIInfoOs.java
new file mode 100644
index 00000000000..a29a957c0ea
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIInfoOs.java
@@ -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 {
+
+ 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;
+
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MIInfoOsInfo.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MIInfoOsInfo.java
new file mode 100644
index 00000000000..9c9f5191812
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MIInfoOsInfo.java
@@ -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 classes = new ArrayList();
+
+ 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());
+ }
+}