diff --git a/InTrace-VisualVM/build.xml b/InTrace-VisualVM/build.xml new file mode 100644 index 0000000..c4f7265 --- /dev/null +++ b/InTrace-VisualVM/build.xml @@ -0,0 +1,8 @@ + + + + + + Builds, tests, and runs the project org.intrace.visualvm. + + diff --git a/InTrace-VisualVM/manifest.mf b/InTrace-VisualVM/manifest.mf new file mode 100644 index 0000000..8dc9c8d --- /dev/null +++ b/InTrace-VisualVM/manifest.mf @@ -0,0 +1,7 @@ +Manifest-Version: 1.0 +OpenIDE-Module: org.intrace.visualvm +OpenIDE-Module-Install: org/intrace/visualvm/Installer.class +OpenIDE-Module-Layer: org/intrace/visualvm/layer.xml +OpenIDE-Module-Localizing-Bundle: org/intrace/visualvm/Bundle.properties +OpenIDE-Module-Specification-Version: 1.0 +OpenIDE-Module-Name: InTrace: VisualVM Plugin diff --git a/InTrace-VisualVM/nbproject/build-impl.xml b/InTrace-VisualVM/nbproject/build-impl.xml new file mode 100644 index 0000000..65a9e86 --- /dev/null +++ b/InTrace-VisualVM/nbproject/build-impl.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/InTrace-VisualVM/nbproject/platform.properties b/InTrace-VisualVM/nbproject/platform.properties new file mode 100644 index 0000000..6221694 --- /dev/null +++ b/InTrace-VisualVM/nbproject/platform.properties @@ -0,0 +1,5 @@ +cluster.path=\ + ${nbplatform.active.dir}/platform:\ + ${nbplatform.active.dir}/profiler:\ + ${nbplatform.active.dir}/visualvm +nbplatform.active=VisualVM_1.2.2 diff --git a/InTrace-VisualVM/nbproject/project.properties b/InTrace-VisualVM/nbproject/project.properties new file mode 100644 index 0000000..9fc050a --- /dev/null +++ b/InTrace-VisualVM/nbproject/project.properties @@ -0,0 +1,3 @@ +cp.extra=${tools.jar} +javac.source=1.6 +javac.compilerargs=-Xlint -Xlint:-serial diff --git a/InTrace-VisualVM/nbproject/project.xml b/InTrace-VisualVM/nbproject/project.xml new file mode 100644 index 0000000..acd7dd1 --- /dev/null +++ b/InTrace-VisualVM/nbproject/project.xml @@ -0,0 +1,72 @@ + + + org.netbeans.modules.apisupport.project + + + org.intrace.visualvm + + + + com.sun.tools.visualvm.application + + + + 0-1 + 1.2 + + + + com.sun.tools.visualvm.attach + + 0-1 + 1.1 + + + + com.sun.tools.visualvm.core + + + + 0-1 + 1.3 + + + + com.sun.tools.visualvm.host + + + + 0-1 + 1.0 + + + + com.sun.tools.visualvm.tools + + + + 0-1 + 1.1 + + + + org.openide.modules + + + + 7.13.1 + + + + org.openide.util + + + + 7.31.1.1 + + + + + + + diff --git a/InTrace-VisualVM/release/modules/ext/intrace-agent.jar b/InTrace-VisualVM/release/modules/ext/intrace-agent.jar new file mode 100644 index 0000000..3531c86 Binary files /dev/null and b/InTrace-VisualVM/release/modules/ext/intrace-agent.jar differ diff --git a/InTrace-VisualVM/release/modules/ext/intrace-client-cui.jar b/InTrace-VisualVM/release/modules/ext/intrace-client-cui.jar new file mode 100644 index 0000000..8d9e3c7 Binary files /dev/null and b/InTrace-VisualVM/release/modules/ext/intrace-client-cui.jar differ diff --git a/InTrace-VisualVM/release/modules/ext/intrace-client-gui-linux.jar b/InTrace-VisualVM/release/modules/ext/intrace-client-gui-linux.jar new file mode 100644 index 0000000..615c195 Binary files /dev/null and b/InTrace-VisualVM/release/modules/ext/intrace-client-gui-linux.jar differ diff --git a/InTrace-VisualVM/release/modules/ext/intrace-client-gui-win.jar b/InTrace-VisualVM/release/modules/ext/intrace-client-gui-win.jar new file mode 100644 index 0000000..ee11b78 Binary files /dev/null and b/InTrace-VisualVM/release/modules/ext/intrace-client-gui-win.jar differ diff --git a/InTrace-VisualVM/src/org/intrace/visualvm/Bundle.properties b/InTrace-VisualVM/src/org/intrace/visualvm/Bundle.properties new file mode 100644 index 0000000..3fb8fa9 --- /dev/null +++ b/InTrace-VisualVM/src/org/intrace/visualvm/Bundle.properties @@ -0,0 +1 @@ +OpenIDE-Module-Name=InTrace: Visual VM Plugin diff --git a/InTrace-VisualVM/src/org/intrace/visualvm/Installer.java b/InTrace-VisualVM/src/org/intrace/visualvm/Installer.java new file mode 100644 index 0000000..217ced7 --- /dev/null +++ b/InTrace-VisualVM/src/org/intrace/visualvm/Installer.java @@ -0,0 +1,20 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.intrace.visualvm; + +import org.intrace.visualvm.view.InTraceViewProvider; +import org.openide.modules.ModuleInstall; + +/** + * Manages a module's lifecycle. Remember that an installer is optional and + * often not needed at all. + */ +public class Installer extends ModuleInstall { + + @Override + public void restored() { + InTraceViewProvider.initialize(); + } +} diff --git a/InTrace-VisualVM/src/org/intrace/visualvm/Locator.java b/InTrace-VisualVM/src/org/intrace/visualvm/Locator.java new file mode 100644 index 0000000..11f100f --- /dev/null +++ b/InTrace-VisualVM/src/org/intrace/visualvm/Locator.java @@ -0,0 +1,50 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.intrace.visualvm; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import org.openide.modules.InstalledFileLocator; + +/** + * + * @author mch50 + */ +public class Locator { + + public static final String agentPath; + public static final String clientPath; + + static { + File locatedFile = InstalledFileLocator.getDefault().locate("modules/ext/intrace-agent.jar", null, false); // NOI18N + if (locatedFile != null) { + agentPath = locatedFile.getAbsolutePath(); + } else { + agentPath = null; + } + + String osName = System.getProperty("os.name", "unknown"); + if (osName.contains("Windows")) { + locatedFile = InstalledFileLocator.getDefault().locate("modules/ext/intrace-client-gui-win.jar", null, false); // NOI18N + if (locatedFile != null) { + clientPath = locatedFile.getAbsolutePath(); + } else { + clientPath = null; + } + } + else if (osName.contains("Linux")) { + locatedFile = InstalledFileLocator.getDefault().locate("modules/ext/intrace-client-gui-linux.jar", null, false); // NOI18N + if (locatedFile != null) { + clientPath = locatedFile.getAbsolutePath(); + } else { + clientPath = null; + } + } + else { + clientPath = null; + } + } +} diff --git a/InTrace-VisualVM/src/org/intrace/visualvm/actions/Bundle.properties b/InTrace-VisualVM/src/org/intrace/visualvm/actions/Bundle.properties new file mode 100644 index 0000000..eea8ea3 --- /dev/null +++ b/InTrace-VisualVM/src/org/intrace/visualvm/actions/Bundle.properties @@ -0,0 +1 @@ +InTraceApplicationAction.title=InTrace Application... \ No newline at end of file diff --git a/InTrace-VisualVM/src/org/intrace/visualvm/actions/InTraceApplicationAction.java b/InTrace-VisualVM/src/org/intrace/visualvm/actions/InTraceApplicationAction.java new file mode 100644 index 0000000..32edbd4 --- /dev/null +++ b/InTrace-VisualVM/src/org/intrace/visualvm/actions/InTraceApplicationAction.java @@ -0,0 +1,43 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package org.intrace.visualvm.actions; + +import com.sun.tools.visualvm.application.Application; +import com.sun.tools.visualvm.application.jvm.Jvm; +import com.sun.tools.visualvm.application.jvm.JvmFactory; +import com.sun.tools.visualvm.core.ui.DataSourceWindowManager; +import com.sun.tools.visualvm.core.ui.actions.SingleDataSourceAction; +import java.awt.event.ActionEvent; +import org.intrace.visualvm.impl.InTraceDataSource; +import org.openide.util.NbBundle; + +/** + * + * @author mch50 + */ +public class InTraceApplicationAction extends SingleDataSourceAction { + + @Override + protected void actionPerformed(Application app, ActionEvent actionEvent) { + InTraceDataSource dataSource = new InTraceDataSource(app); + DataSourceWindowManager.sharedInstance().openDataSource(dataSource); + } + + @Override + protected boolean isEnabled(Application app) { + Jvm jvm = JvmFactory.getJVMFor(app); + return app.isLocalApplication() && jvm.isAttachable() && jvm.isGetSystemPropertiesSupported(); + } + + public static synchronized InTraceApplicationAction newInstance() { + return new InTraceApplicationAction(); + } + + private InTraceApplicationAction() { + super(Application.class); + putValue(NAME, NbBundle.getMessage(InTraceApplicationAction.class, "InTraceApplicationAction.title")); // NOI18N + } +} diff --git a/InTrace-VisualVM/src/org/intrace/visualvm/impl/InTraceDataSource.java b/InTrace-VisualVM/src/org/intrace/visualvm/impl/InTraceDataSource.java new file mode 100644 index 0000000..e51f683 --- /dev/null +++ b/InTrace-VisualVM/src/org/intrace/visualvm/impl/InTraceDataSource.java @@ -0,0 +1,23 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package org.intrace.visualvm.impl; + +import com.sun.tools.visualvm.application.Application; +import com.sun.tools.visualvm.core.datasource.DataSource; + +/** + * + * @author mch50 + */ +public class InTraceDataSource extends DataSource { + + public final Application app; + + public InTraceDataSource(Application app) { + super(app); + this.app = app; + } +} diff --git a/InTrace-VisualVM/src/org/intrace/visualvm/impl/InTraceLoader.java b/InTrace-VisualVM/src/org/intrace/visualvm/impl/InTraceLoader.java new file mode 100644 index 0000000..1abbf2f --- /dev/null +++ b/InTrace-VisualVM/src/org/intrace/visualvm/impl/InTraceLoader.java @@ -0,0 +1,89 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.intrace.visualvm.impl; + +import com.sun.tools.attach.VirtualMachine; +import com.sun.tools.visualvm.application.Application; +import com.sun.tools.visualvm.application.jvm.Jvm; +import com.sun.tools.visualvm.application.jvm.JvmFactory; +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import org.intrace.visualvm.Locator; +import org.openide.util.Exceptions; + +/** + * + * @author mch50 + */ +public class InTraceLoader { + + public static interface StatusHandler { + + public void handleStatus(String statusLine); + } + + public static void loadAgent(Application app, StatusHandler handler) { + Jvm jvm = JvmFactory.getJVMFor(app); + if (app.isLocalApplication() && jvm.isAttachable() && jvm.isGetSystemPropertiesSupported()) { + try { + VirtualMachine vm = VirtualMachine.attach(String.valueOf(app.getPid())); + handler.handleStatus("Attached to JVM (PID: " + app.getPid() + ")"); + vm.loadAgent(Locator.agentPath, ""); + handler.handleStatus("InTrace Agent loaded"); + } catch (Exception ex) { + handler.handleStatus("Exception thrown:\n" + throwableToString(ex)); + Exceptions.printStackTrace(ex); + } + } + } + + public static void launchClient(final StatusHandler handler) { + Runnable launchClientThread = new Runnable() { + + @Override + public void run() { + try { + List command = new ArrayList(); + command.add("java"); + command.add("-jar"); + command.add(Locator.clientPath); + + ProcessBuilder builder = new ProcessBuilder(command); + + System.out.println("Directory : " + System.getenv("temp")); + builder.start(); + + handler.handleStatus("InTrace Client launched"); + } catch (Exception ex) { + handler.handleStatus("Exception thrown:\n" + throwableToString(ex)); + Exceptions.printStackTrace(ex); + } + } + }; + new Thread(launchClientThread).start(); + } + + private static String throwableToString(Throwable throwable) { + StringBuilder throwToStr = new StringBuilder(); + if (throwable == null) { + throwToStr.append("null"); + } else { + StringWriter strWriter = new StringWriter(); + PrintWriter writer = new PrintWriter(strWriter); + throwable.printStackTrace(writer); + throwToStr.append(strWriter.toString()); + } + return throwToStr.toString(); + } +} diff --git a/InTrace-VisualVM/src/org/intrace/visualvm/layer.xml b/InTrace-VisualVM/src/org/intrace/visualvm/layer.xml new file mode 100644 index 0000000..035037b --- /dev/null +++ b/InTrace-VisualVM/src/org/intrace/visualvm/layer.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/InTrace-VisualVM/src/org/intrace/visualvm/view/InTraceView.java b/InTrace-VisualVM/src/org/intrace/visualvm/view/InTraceView.java new file mode 100644 index 0000000..9fb6664 --- /dev/null +++ b/InTrace-VisualVM/src/org/intrace/visualvm/view/InTraceView.java @@ -0,0 +1,144 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package org.intrace.visualvm.view; + +import com.sun.tools.visualvm.core.ui.DataSourceView; +import com.sun.tools.visualvm.core.ui.components.DataViewComponent; +import java.awt.BorderLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.BorderFactory; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import org.intrace.visualvm.Locator; +import org.intrace.visualvm.impl.InTraceLoader; +import org.intrace.visualvm.impl.InTraceDataSource; +import org.openide.util.Utilities; + +/** + * + * @author mch50 + */ +public class InTraceView extends DataSourceView { + + private final InTraceDataSource application; + + private JTextArea textArea; + private DataViewComponent dvc; + + //Reusing an image from the sources: + private static final String IMAGE_PATH = "com/sun/tools/visualvm/coredump/resources/coredump.png"; // NOI18N + + public InTraceView(InTraceDataSource application) { + super(application, "InTrace", new ImageIcon(Utilities.loadImage(IMAGE_PATH, true)).getImage(), 60, false); + this.application = application; + } + + @Override + protected DataViewComponent createComponent() { + + //Data area for master view: + JPanel generalDataArea = new JPanel(); + generalDataArea.setBorder(BorderFactory.createEmptyBorder(14, 8, 14, 8)); + generalDataArea.setOpaque(false); + + JButton loadAgentButton = new JButton("Load InTrace Agent"); + loadAgentButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + InTraceLoader.loadAgent(application.app, new InTraceLoader.StatusHandler() { + @Override + public void handleStatus(String statusLine) { + appendText(statusLine); + } + }); + } + }); + + JButton launchClient = new JButton("Launch InTrace Client"); + launchClient.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + InTraceLoader.launchClient(new InTraceLoader.StatusHandler() { + @Override + public void handleStatus(String statusLine) { + appendText(statusLine); + } + }); + } + }); + + JButton clearStatus = new JButton("Clear Status Text"); + clearStatus.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + clearText(); + } + }); + + generalDataArea.add(loadAgentButton); + generalDataArea.add(launchClient); + generalDataArea.add(clearStatus); + + //Master view: + DataViewComponent.MasterView masterView = new DataViewComponent.MasterView + ("Control", null, generalDataArea); + + //Configuration of master view: + DataViewComponent.MasterViewConfiguration masterConfiguration = + new DataViewComponent.MasterViewConfiguration(false); + + //Add the master view and configuration view to the component: + dvc = new DataViewComponent(masterView, masterConfiguration); + + //Add detail view to the component: + + JPanel statusArea = new JPanel(); + statusArea.setOpaque(false); + statusArea.setLayout(new BorderLayout()); + + textArea = new JTextArea(5, 20); + JScrollPane scrollPane = new JScrollPane(textArea); + scrollPane.setVerticalScrollBarPolicy( + JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); + textArea.setEditable(false); + textArea.setLineWrap(true); + textArea.setMargin(new Insets(10,10,10,10)); + + statusArea.add(scrollPane, BorderLayout.CENTER); + + dvc.addDetailsView(new DataViewComponent.DetailsView( + "Status", null, 10, statusArea, null), DataViewComponent.BOTTOM_LEFT); + + appendText("Agent Path: " + Locator.agentPath); + appendText("Client Path: " + Locator.clientPath); + if (Locator.clientPath == null) { + appendText("Warning: The Client is only supported on Windows " + + "and Linux"); + } + else { + appendText("Ready"); + } + + return dvc; + } + + private void appendText(String str) { + if (textArea != null) { + textArea.append(str + "\n"); + } + } + + private void clearText() { + if (textArea != null) { + textArea.setText(""); + } + } +} diff --git a/InTrace-VisualVM/src/org/intrace/visualvm/view/InTraceViewProvider.java b/InTrace-VisualVM/src/org/intrace/visualvm/view/InTraceViewProvider.java new file mode 100644 index 0000000..648543a --- /dev/null +++ b/InTrace-VisualVM/src/org/intrace/visualvm/view/InTraceViewProvider.java @@ -0,0 +1,39 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package org.intrace.visualvm.view; + +import com.sun.tools.visualvm.core.ui.DataSourceView; +import com.sun.tools.visualvm.core.ui.DataSourceViewProvider; +import com.sun.tools.visualvm.core.ui.DataSourceViewsManager; +import org.intrace.visualvm.impl.InTraceDataSource; + +/** + * + * @author mch50 + */ +public class InTraceViewProvider extends DataSourceViewProvider { + + private static DataSourceViewProvider instance = new InTraceViewProvider(); + + @Override + public boolean supportsViewFor(InTraceDataSource application) { + //Always shown: + return true; + } + + @Override + public synchronized DataSourceView createView(final InTraceDataSource application) { + return new InTraceView(application); + } + + public static void initialize() { + DataSourceViewsManager.sharedInstance().addViewProvider(instance, InTraceDataSource.class); + } + + static void unregister() { + DataSourceViewsManager.sharedInstance().removeViewProvider(instance); + } +} diff --git a/binaries/jars/latest_development/org-intrace-visualvm.nbm b/binaries/jars/latest_development/org-intrace-visualvm.nbm new file mode 100644 index 0000000..c2c1bd1 Binary files /dev/null and b/binaries/jars/latest_development/org-intrace-visualvm.nbm differ