diff --git a/visualvm/application/src/com/sun/tools/visualvm/application/ApplicationMethod.java b/visualvm/application/src/com/sun/tools/visualvm/application/ApplicationMethod.java
new file mode 100644
index 0000000000..731a93d7ff
--- /dev/null
+++ b/visualvm/application/src/com/sun/tools/visualvm/application/ApplicationMethod.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.tools.visualvm.application;
+
+import java.awt.event.ActionListener;
+
+/** Represents an application method. This is a data class that
+ * holds a reference to an {@link Application} and a method selected,
+ * for example inside of a sampling window. To register an action to
+ * CPU sampling window do:
+ *
+{@code @}Messages({
+ "LAB_Show=Show selected method"
+})
+{@code @}ActionID(category = "VisualVM", id = "my.pkg.test.Show")
+{@code @}ActionRegistration(displayName = "#LAB_Show", iconBase = "my/pkg/test/show.gif")
+{@code @}ActionReference(path = "VisualVM/CPUView")
+public class Show implements ActionListener {
+ private final ApplicationMethod am;
+
+ public Show(ApplicationMethod am) {
+ this.am = am;
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ JOptionPane.showMessage(null, "Selected: " + am.getClassName());
+ }
+}
+
+ * With that your action will be shown in a toolbar of CPU view and can
+ * operate on {@link ApplicationMethod} instance once it is
+ * {@link ActionListener#actionPerformed(java.awt.event.ActionEvent) invoked}.
+ */
+public final class ApplicationMethod {
+ private final Application app;
+ private final String className;
+ private final String methodName;
+ private final String signature;
+
+ /** Constructor.
+ *
+ * @param app application available via {@link #getApplication()}
+ * @param className class name available via {@link #getClassName() ()}
+ * @param methodName method name available via {@link #getMethodName()}
+ * @param signature method signature available via {@link #getSignature()}
+ */
+ public ApplicationMethod(Application app, String className, String methodName, String signature) {
+ this.app = app;
+ this.className = className;
+ this.methodName = methodName;
+ this.signature = signature;
+ }
+
+ /** Reference to associated application.
+ *
+ * @return the application VisualVM is connected to
+ */
+ public Application getApplication() {
+ return app;
+ }
+
+ /** Fully quallified class name.
+ *
+ * @return name of selected class
+ */
+ public String getClassName() {
+ return className;
+ }
+
+ /** Method name.
+ *
+ * @return name of selected method
+ */
+ public String getMethodName() {
+ return methodName;
+ }
+
+ /** Signature of the selected method.
+ *
+ * @return signature of the method
+ */
+ public String getSignature() {
+ return signature;
+ }
+}
diff --git a/visualvm/core/nbproject/project.xml b/visualvm/core/nbproject/project.xml
index a3e346bdfa..a83b138436 100644
--- a/visualvm/core/nbproject/project.xml
+++ b/visualvm/core/nbproject/project.xml
@@ -58,6 +58,15 @@
1.10.1
+
+ org.netbeans.lib.profiler.common
+
+
+
+ 1
+ 1.32.1
+
+
org.netbeans.modules.autoupdate.services
diff --git a/visualvm/sampler/nbproject/project.xml b/visualvm/sampler/nbproject/project.xml
index 4b232dea18..308b720ffe 100644
--- a/visualvm/sampler/nbproject/project.xml
+++ b/visualvm/sampler/nbproject/project.xml
@@ -132,6 +132,14 @@
1.1
+
+ org.openide.awt
+
+
+
+ 7.62
+
+
org.openide.dialogs
@@ -149,19 +157,19 @@
- org.openide.util
+ org.openide.util.lookup
- 8.6.1
+ 8.11
- org.openide.util.lookup
+ org.openide.util
- 8.11
+ 8.39
diff --git a/visualvm/sampler/src/com/sun/tools/visualvm/sampler/SamplerImpl.java b/visualvm/sampler/src/com/sun/tools/visualvm/sampler/SamplerImpl.java
index d297fb260d..5d1698245c 100644
--- a/visualvm/sampler/src/com/sun/tools/visualvm/sampler/SamplerImpl.java
+++ b/visualvm/sampler/src/com/sun/tools/visualvm/sampler/SamplerImpl.java
@@ -542,7 +542,7 @@ public void takeThreadDump(boolean openView) {
}
};
- cpuSampler = new CPUSamplerSupport(ti, tcpu, snapshotDumper, threadDumper) {
+ cpuSampler = new CPUSamplerSupport(application, ti, tcpu, snapshotDumper, threadDumper) {
protected Timer getTimer() { return SamplerImpl.this.getTimer(); }
};
SwingUtilities.invokeLater(new Runnable() {
diff --git a/visualvm/sampler/src/com/sun/tools/visualvm/sampler/cpu/CPUSamplerSupport.java b/visualvm/sampler/src/com/sun/tools/visualvm/sampler/cpu/CPUSamplerSupport.java
index e9d56a8345..5071786e67 100644
--- a/visualvm/sampler/src/com/sun/tools/visualvm/sampler/cpu/CPUSamplerSupport.java
+++ b/visualvm/sampler/src/com/sun/tools/visualvm/sampler/cpu/CPUSamplerSupport.java
@@ -25,6 +25,7 @@
package com.sun.tools.visualvm.sampler.cpu;
+import com.sun.tools.visualvm.application.Application;
import com.sun.tools.visualvm.core.datasupport.Utils;
import com.sun.tools.visualvm.core.options.GlobalPreferences;
import com.sun.tools.visualvm.core.ui.components.DataViewComponent;
@@ -82,8 +83,10 @@ public abstract class CPUSamplerSupport extends AbstractSamplerSupport {
private Refresher threadCPURefresher;
private ThreadsCPUView threadCPUView;
private ThreadsCPU threadsCPU;
+ private final Application app;
- public CPUSamplerSupport(ThreadInfoProvider tip, ThreadsCPU tcpu, SnapshotDumper snapshotDumper, ThreadDumper threadDumper) {
+ public CPUSamplerSupport(Application app, ThreadInfoProvider tip, ThreadsCPU tcpu, SnapshotDumper snapshotDumper, ThreadDumper threadDumper) {
+ this.app = app;
threadInfoProvider = tip;
threadsCPU = tcpu;
this.snapshotDumper = snapshotDumper;
@@ -131,7 +134,7 @@ public final int getRefreshRate() {
public DataViewComponent.DetailsView[] getDetailsView() {
if (detailsViews == null) {
- cpuView = new CPUView(refresher, snapshotDumper, threadDumper);
+ cpuView = new CPUView(app, refresher, snapshotDumper, threadDumper);
detailsViews = new DataViewComponent.DetailsView[threadsCPU != null ? 2:1];
detailsViews[0] = new DataViewComponent.DetailsView(NbBundle.getMessage(
CPUSamplerSupport.class, "LBL_Cpu_samples"), null, 10, cpuView, null); // NOI18N
diff --git a/visualvm/sampler/src/com/sun/tools/visualvm/sampler/cpu/CPUView.java b/visualvm/sampler/src/com/sun/tools/visualvm/sampler/cpu/CPUView.java
index a25465fd6b..9e158aca60 100644
--- a/visualvm/sampler/src/com/sun/tools/visualvm/sampler/cpu/CPUView.java
+++ b/visualvm/sampler/src/com/sun/tools/visualvm/sampler/cpu/CPUView.java
@@ -25,25 +25,42 @@
package com.sun.tools.visualvm.sampler.cpu;
+import com.sun.tools.visualvm.application.Application;
+import com.sun.tools.visualvm.application.ApplicationMethod;
import com.sun.tools.visualvm.sampler.AbstractSamplerSupport;
import com.sun.tools.visualvm.uisupport.TransparentToolBar;
import java.awt.BorderLayout;
+import java.awt.Component;
import java.awt.Dimension;
+import java.awt.EventQueue;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
+import java.util.List;
+import java.util.MissingResourceException;
+import java.util.concurrent.TimeUnit;
import javax.swing.AbstractButton;
+import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
+import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
+import javax.swing.JTable;
import javax.swing.JToggleButton;
import javax.swing.SwingConstants;
-import org.openide.util.ImageUtilities;
-import org.openide.util.NbBundle;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.event.TableModelEvent;
+import javax.swing.event.TableModelListener;
+import org.netbeans.lib.profiler.client.ClientUtils;
+import org.openide.awt.Actions;
+import org.openide.util.*;
+import org.openide.util.lookup.AbstractLookup;
+import org.openide.util.lookup.InstanceContent;
/**
*
@@ -60,13 +77,13 @@ final class CPUView extends JPanel {
private SampledLivePanel resultsPanel;
- CPUView(AbstractSamplerSupport.Refresher refresher, CPUSamplerSupport.SnapshotDumper
+ CPUView(Application app, AbstractSamplerSupport.Refresher refresher, CPUSamplerSupport.SnapshotDumper
snapshotDumper, CPUSamplerSupport.ThreadDumper threadDumper) {
this.refresher = refresher;
this.snapshotDumper = snapshotDumper;
this.threadDumper = threadDumper;
- initComponents();
+ initComponents(app);
addHierarchyListener(new HierarchyListener() {
public void hierarchyChanged(HierarchyEvent e) {
@@ -124,7 +141,7 @@ void terminate() {
}
- private void initComponents() {
+ private void initComponents(Application app) {
setLayout(new BorderLayout());
setOpaque(false);
@@ -193,7 +210,10 @@ protected void fireActionPerformed(ActionEvent event) {
snapshotButton.setOpaque(false);
snapshotButton.setEnabled(false);
toolBar.addItem(snapshotButton);
-
+
+ toolBar.addSeparator();
+ fillInToolbar(app, toolBar);
+
toolBar.addFiller();
threaddumpButton = new JButton(NbBundle.getMessage(CPUView.class, "LBL_Thread_dump")) { // NOI18N
@@ -242,6 +262,96 @@ protected void fireActionPerformed(ActionEvent event) {
}
+ private void fillInToolbar(final Application app, final TransparentToolBar toolBar) throws MissingResourceException {
+ List extends Action> actions = Utilities.actionsForPath("VisualVM/CPUView");
+ final InstanceContent ic = new InstanceContent();
+ ic.add(app);
+ AbstractLookup lookup = new AbstractLookup(ic);
+ class L implements TableModelListener, Runnable, ListSelectionListener {
+ ClientUtils.SourceCodeSelection sss;
+ ApplicationMethod am;
+
+ @Override
+ public void tableChanged(TableModelEvent e) {
+ JTable t = findJTable(CPUView.this);
+ if (t == null) {
+ return;
+ }
+ int row = t.getSelectedRow();
+ if (sss != null) {
+ ic.remove(sss);
+ }
+ if (am != null) {
+ ic.remove(am);
+ }
+ if (row == -1) {
+ return;
+ }
+ String classAndMethod = t.getModel().getValueAt(row, 0).toString();
+ int lastDot = classAndMethod.lastIndexOf('.');
+ String clazzName = classAndMethod.substring(0, lastDot);
+ int param = classAndMethod.lastIndexOf('(');
+ if (param == -1) {
+ param = classAndMethod.length();
+ }
+ String methodName = classAndMethod.substring(lastDot + 1, param);
+ String signature = classAndMethod.substring(param);
+
+ ic.add(sss = new ClientUtils.SourceCodeSelection(clazzName, methodName, signature));
+ ic.add(am = new ApplicationMethod(app, clazzName, methodName, signature));
+ }
+
+ @Override
+ public void run() {
+ if (EventQueue.isDispatchThread()) {
+ JTable t = findJTable(CPUView.this);
+ if (t != null) {
+ t.getSelectionModel().addListSelectionListener(this);
+ } else {
+ RequestProcessor.getDefault().schedule(this, 100, TimeUnit.MILLISECONDS);
+ }
+ tableChanged(null);
+ } else {
+ EventQueue.invokeLater(this);
+ }
+ }
+
+ @Override
+ public void valueChanged(ListSelectionEvent e) {
+ tableChanged(null);
+ }
+ }
+ final L listener = new L();
+ listener.run();
+
+ for (Action a : actions) {
+ if (a instanceof ContextAwareAction) {
+ a = ((ContextAwareAction) a).createContextAwareInstance(lookup);
+ }
+ JButton b = new JButton();
+ Actions.connect(b, a);
+// b.setText((String) a.getValue(Action.NAME));
+// b.addActionListener(a);
+// b.setOpaque(false);
+ toolBar.addItem(b);
+ }
+ }
+
+ private static JTable findJTable(Component c) {
+ if (c instanceof JTable) {
+ return (JTable) c;
+ }
+ if (c instanceof JComponent) {
+ Component[] arr = ((JComponent) c).getComponents();
+ for (Component component : arr) {
+ JTable t = findJTable(component);
+ if (t != null) {
+ return t;
+ }
+ }
+ }
+ return null;
+ }
// private JLabel refreshRateLabel;
// private JLabel refreshUnitsLabel;