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 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;