Index: src/org/eclipse/mat/ui/Messages.java
===================================================================
--- src/org/eclipse/mat/ui/Messages.java (revision 386)
+++ src/org/eclipse/mat/ui/Messages.java (working copy)
@@ -96,7 +96,8 @@
public static String InspectorView_LinkWithSnapshot;
public static String InspectorView_Name;
public static String InspectorView_noGCRoot;
- public static String InspectorView_PinTab;
+ public static String InspectorView_Path;
+ public static String InspectorView_PinTab;
public static String InspectorView_retainedSize;
public static String InspectorView_shallowSize;
public static String InspectorView_Statics;
@@ -266,6 +267,8 @@
public static String OverviewPane_ComponentReport;
public static String OverviewPane_NoPieChartAvailable;
public static String InspectorView_GCroot;
+ public static String InspectorView_ReferenceName;
+ public static String InspectorView_ReferingObject;
static
{
Index: src/org/eclipse/mat/ui/messages.properties
===================================================================
--- src/org/eclipse/mat/ui/messages.properties (revision 386)
+++ src/org/eclipse/mat/ui/messages.properties (working copy)
@@ -90,6 +90,7 @@
InspectorView_LinkWithSnapshot=Link with Snapshot
InspectorView_Name=Name
InspectorView_noGCRoot=no GC root
+InspectorView_Path=Shortest Path
InspectorView_PinTab=Pin Tab
InspectorView_retainedSize={0,number} (retained size)
InspectorView_shallowSize={0,number} (shallow size)
@@ -260,3 +261,5 @@
OverviewPane_ComponentReport=Component Report
OverviewPane_NoPieChartAvailable=BIRT Chart Engine (>2.2.2) not available. No pie today. Check-out the Dominator Tree or Top Consumers.
InspectorView_GCroot=GC root:
+InspectorView_ReferenceName=Reference Name
+InspectorView_ReferingObject=Referring Object
Index: src/org/eclipse/mat/ui/snapshot/views/inspector/InspectorContextProvider.java
===================================================================
--- src/org/eclipse/mat/ui/snapshot/views/inspector/InspectorContextProvider.java (revision 386)
+++ src/org/eclipse/mat/ui/snapshot/views/inspector/InspectorContextProvider.java (working copy)
@@ -69,6 +69,18 @@
}
};
}
+ else if (row instanceof PathNode)
+ {
+ final PathNode node = (PathNode) row;
+
+ return new IContextObject()
+ {
+ public int getObjectId()
+ {
+ return node.getObjectId();
+ }
+ };
+ }
return null;
}
catch (SnapshotException e)
Index: src/org/eclipse/mat/ui/snapshot/views/inspector/InspectorView.java
===================================================================
--- src/org/eclipse/mat/ui/snapshot/views/inspector/InspectorView.java (revision 386)
+++ src/org/eclipse/mat/ui/snapshot/views/inspector/InspectorView.java (working copy)
@@ -47,6 +47,7 @@
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.mat.SnapshotException;
import org.eclipse.mat.query.IContextObject;
+import org.eclipse.mat.snapshot.IPathsFromGCRootsComputer;
import org.eclipse.mat.snapshot.ISnapshot;
import org.eclipse.mat.snapshot.model.GCRootInfo;
import org.eclipse.mat.snapshot.model.IClass;
@@ -106,6 +107,7 @@
private CTabFolder tabFolder;
private TableViewer attributesTable;
private TableViewer staticsTable;
+ private TableViewer pathTable;
private TreeViewer classHierarchyTree;
private boolean pinSelection = false;
private Font font;
@@ -504,6 +506,11 @@
classHierarchyTab.setText(Messages.InspectorView_ClassHierarchy);
classHierarchyTree = createHierarchyTree(tabFolder);
classHierarchyTab.setControl(classHierarchyTree.getTree().getParent());
+
+ CTabItem pathTab = new CTabItem(tabFolder, SWT.NULL);
+ pathTab.setText(Messages.InspectorView_Path);
+ pathTable = createPathTable(tabFolder);
+ pathTab.setControl(pathTable.getTable().getParent());
tabFolder.setSelection(0);
}
@@ -524,6 +531,42 @@
return classHierarchyTree;
}
+
+ private TableViewer createPathTable(Composite parent)
+ {
+ Composite composite = new Composite(parent, SWT.NONE);
+ TableColumnLayout columnLayout = new TableColumnLayout();
+ composite.setLayout(columnLayout);
+ GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).applyTo(composite);
+
+ final TableViewer viewer = new TableViewer(composite, SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
+ Table table = viewer.getTable();
+ viewer.setContentProvider(new FieldsContentProvider());
+ viewer.setLabelProvider(new PathLabelProvider(this, table.getFont()));
+
+ getViewSite().getActionBars().setGlobalActionHandler(ActionFactory.COPY.getId(), new Action()
+ {
+ @Override
+ public void run()
+ {
+ Copy.copyToClipboard(viewer.getControl());
+ }
+ });
+
+ TableColumn tableColumn = new TableColumn(table, SWT.LEFT);
+ tableColumn.setWidth(80);
+ tableColumn.setText(Messages.InspectorView_ReferenceName);
+ columnLayout.setColumnData(tableColumn, new ColumnWeightData(30, 40));
+
+ tableColumn = new TableColumn(table, SWT.LEFT);
+ tableColumn.setWidth(250);
+ tableColumn.setText(Messages.InspectorView_ReferingObject);
+ columnLayout.setColumnData(tableColumn, new ColumnWeightData(60, 250, true));
+
+ table.setHeaderVisible(true);
+
+ return viewer;
+ }
private TableViewer createTable(Composite parent)
{
@@ -572,6 +615,7 @@
createMenu(attributesTable);
createMenu(topTableViewer);
createMenu(classHierarchyTree);
+ createMenu(pathTable);
}
private void createMenu(StructuredViewer viewer)
@@ -808,6 +852,9 @@
// prepare attributes
final LazyFields> attributeFields = prepareAttributes(object);
+
+ // prepare path
+ final LazyFields> pathFields = preparePath(object);
// update visual viewer
final Object toShow = prepareVisualInfo(object);
@@ -820,6 +867,7 @@
topTableViewer.setData("input", objectId);//$NON-NLS-1$
staticsTable.setInput(staticFields);
attributesTable.setInput(attributeFields);
+ pathTable.setInput(pathFields);
updateVisualViewer(toShow);
IClass input = object instanceof IClass ? (IClass) object : object.getClazz();
@@ -952,6 +1000,15 @@
return fields;
}
+
+ private LazyFields> preparePath(final IObject object) throws SnapshotException
+ {
+ IPathsFromGCRootsComputer pathComputer = snapshot.getPathsFromGCRoots(object.getObjectId(), null);
+ int[] path = pathComputer.getNextShortestPath();
+
+ return new LazyFields.Path(object, path);
+ }
+
private LazyFields> prepareStaticFields(final IObject object)
{
@@ -1105,6 +1162,11 @@
{
classHierarchyTree.setInput(new Object[] { new Object() });
}
+
+ if (pathTable.getContentProvider() != null)
+ {
+ pathTable.setInput(LazyFields.EMPTY);
+ }
for (Menu menu : contextMenus)
{
Index: src/org/eclipse/mat/ui/snapshot/views/inspector/PathNode.java
===================================================================
--- src/org/eclipse/mat/ui/snapshot/views/inspector/PathNode.java (revision 0)
+++ src/org/eclipse/mat/ui/snapshot/views/inspector/PathNode.java (revision 0)
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2008 SAP AG.
+ * 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:
+ * SAP AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.mat.ui.snapshot.views.inspector;
+
+import org.eclipse.swt.graphics.Image;
+
+/* package */class PathNode
+{
+ String name;
+ int objectId;
+ Image icon;
+
+ public PathNode(String name, int objectId, Image icon)
+ {
+ this.name = name;
+ this.objectId = objectId;
+ this.icon = icon;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public int getObjectId()
+ {
+ return objectId;
+ }
+
+ public Image getIcon()
+ {
+ return icon;
+ }
+}
Index: src/org/eclipse/mat/ui/snapshot/views/inspector/LazyFields.java
===================================================================
--- src/org/eclipse/mat/ui/snapshot/views/inspector/LazyFields.java (revision 386)
+++ src/org/eclipse/mat/ui/snapshot/views/inspector/LazyFields.java (working copy)
@@ -11,6 +11,7 @@
package org.eclipse.mat.ui.snapshot.views.inspector;
import java.lang.ref.WeakReference;
+import java.net.URL;
import java.util.ArrayList;
import java.util.List;
@@ -24,7 +25,10 @@
import org.eclipse.mat.snapshot.model.IPrimitiveArray;
import org.eclipse.mat.snapshot.model.NamedReference;
import org.eclipse.mat.snapshot.model.ObjectReference;
+import org.eclipse.mat.snapshot.query.Icons;
+import org.eclipse.mat.ui.MemoryAnalyserPlugin;
import org.eclipse.mat.ui.Messages;
+import org.eclipse.swt.graphics.Image;
/* package */abstract class LazyFields
{
@@ -202,6 +206,58 @@
}
}
}
+
+ /* package */static class Path extends LazyFields
+ {
+ private int length;
+ int[] path;
+
+ public Path(IObject object, int[] path)
+ {
+ super(object);
+ this.length = path.length;
+ this.path = path;
+ }
+
+ public int getSize()
+ {
+ return length;
+ }
+
+ @Override
+ protected Object createElement(IObject object, int index)
+ {
+ try
+ {
+ ISnapshot snapshot = object.getSnapshot();
+ String refName = getReferenceName(index, snapshot);
+ URL imageURL = index == 0 ? Icons.forObject(snapshot, path[index]) : Icons.inbound(snapshot, path[index]);
+ Image icon = MemoryAnalyserPlugin.getDefault().getImage(imageURL);
+ return new PathNode(refName, path[index], icon);
+ }
+ catch (SnapshotException e) {
+ // as fallback create the node with just the objectId
+ return new PathNode("", path[index], null);
+ }
+ }
+
+ private String getReferenceName(int index, ISnapshot snapshot) throws SnapshotException
+ {
+ if (index == 0)
+ return "";
+
+ IObject from = snapshot.getObject(path[index]);
+
+ List references = from.getOutboundReferences();
+ for (NamedReference namedReference : references)
+ {
+ if (namedReference.getObjectId() == path[index - 1])
+ return namedReference.getName();
+ }
+
+ return "";
+ }
+ }
// //////////////////////////////////////////////////////////////
// private helpers
Index: src/org/eclipse/mat/ui/snapshot/views/inspector/PathLabelProvider.java
===================================================================
--- src/org/eclipse/mat/ui/snapshot/views/inspector/PathLabelProvider.java (revision 0)
+++ src/org/eclipse/mat/ui/snapshot/views/inspector/PathLabelProvider.java (revision 0)
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright (c) 2008 SAP AG.
+ * 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:
+ * SAP AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.mat.ui.snapshot.views.inspector;
+
+import org.eclipse.jface.resource.FontDescriptor;
+import org.eclipse.jface.viewers.ITableFontProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.mat.SnapshotException;
+import org.eclipse.mat.snapshot.model.IObject;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Display;
+
+class PathLabelProvider extends LabelProvider implements ITableLabelProvider, ITableFontProvider
+{
+ private final InspectorView inspectorView;
+ private Font italicFont;
+ private Font boldFont;
+
+ public PathLabelProvider(InspectorView inspectorView, Font defaultFont)
+ {
+ this.inspectorView = inspectorView;
+ FontDescriptor fontDescriptor = FontDescriptor.createFrom(defaultFont);
+ this.italicFont = fontDescriptor.setStyle(SWT.ITALIC).createFont(Display.getDefault());
+ this.boldFont = fontDescriptor.setStyle(SWT.BOLD).createFont(Display.getDefault());
+ }
+
+ public Image getColumnImage(Object element, int columnIndex)
+ {
+ if (element instanceof PathNode)
+ {
+ if (columnIndex == 0)
+ {
+ return ((PathNode) element).getIcon();
+ }
+ }
+ return null;
+ }
+
+ public String getColumnText(Object element, int columnIndex)
+ {
+
+ if (element instanceof PathNode)
+ {
+ PathNode node = ((PathNode) element);
+ switch (columnIndex)
+ {
+ case 0:
+ return node.getName();
+ case 1:
+ return getObjectLabel(node.getObjectId());
+ }
+ }
+
+ return null;
+ }
+
+ private String getObjectLabel(int objectId)
+ {
+ try
+ {
+ IObject object = this.inspectorView.snapshot.getObject(objectId);
+ String text = object.getDisplayName();
+ return text;
+ }
+ catch (SnapshotException e)
+ {
+ // $JL-EXC$
+ return "";//$NON-NLS-1$
+ }
+ }
+
+ public Font getFont(Object element, int columnIndex)
+ {
+ if (columnIndex == 0)
+ {
+ return boldFont;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ @Override
+ public void dispose()
+ {
+ italicFont.dispose();
+ boldFont.dispose();
+ }
+
+}