/*
* Copyright (c) 2007, 2011, 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.views.overview;
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.application.snapshot.ApplicationSnapshot;
import com.sun.tools.visualvm.core.datasource.DataSource;
import com.sun.tools.visualvm.core.datasource.descriptor.DataSourceDescriptor;
import com.sun.tools.visualvm.core.datasource.descriptor.DataSourceDescriptorFactory;
import com.sun.tools.visualvm.core.snapshot.Snapshot;
import com.sun.tools.visualvm.core.datasupport.DataChangeEvent;
import com.sun.tools.visualvm.core.datasupport.DataChangeListener;
import com.sun.tools.visualvm.core.datasupport.Positionable;
import com.sun.tools.visualvm.core.snapshot.RegisteredSnapshotCategories;
import com.sun.tools.visualvm.core.snapshot.SnapshotCategory;
import com.sun.tools.visualvm.core.ui.DataSourceWindowManager;
import com.sun.tools.visualvm.core.ui.components.DataViewComponent;
import com.sun.tools.visualvm.core.ui.components.NotSupportedDisplayer;
import com.sun.tools.visualvm.core.ui.components.ScrollableContainer;
import com.sun.tools.visualvm.uisupport.HTMLTextArea;
import java.awt.BorderLayout;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import org.openide.util.NbBundle;
import org.openide.util.WeakListeners;
/**
* A public entrypoint to the Overview subtab.
*
* @author Jiri Sedlacek
* @author Tomas Hurka
*/
class OverviewViewSupport {
// --- General data --------------------------------------------------------
static class MasterViewSupport extends JPanel {
private PropertyChangeListener oomeListener;
public MasterViewSupport(ApplicationOverviewModel model) {
initComponents(model);
}
public DataViewComponent.MasterView getMasterView() {
return new DataViewComponent.MasterView(NbBundle.getMessage(OverviewViewSupport.class, "LBL_Overview"), null, this); // NOI18N
}
private void initComponents(final ApplicationOverviewModel model) {
setLayout(new BorderLayout());
setOpaque(false);
final HTMLTextArea area = new HTMLTextArea("<nobr>" + getGeneralProperties(model) + "</nobr>"); // NOI18N
area.setBorder(BorderFactory.createEmptyBorder(14, 8, 14, 8));
DataSource source = model.getSource();
if (source instanceof Application) {
oomeListener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
if (Jvm.PROPERTY_DUMP_OOME_ENABLED.equals(evt.getPropertyName())) {
int selStart = area.getSelectionStart();
int selEnd = area.getSelectionEnd();
area.setText("<nobr>" + getGeneralProperties(model) + "</nobr>"); // NOI18N
area.select(selStart, selEnd);
}
}
};
Jvm jvm = JvmFactory.getJVMFor((Application)source);
jvm.addPropertyChangeListener(WeakListeners.propertyChange(oomeListener,jvm));
}
add(area, BorderLayout.CENTER);
}
private String getGeneralProperties(ApplicationOverviewModel model) {
StringBuilder data = new StringBuilder();
// Application information
String PID = NbBundle.getMessage(OverviewViewSupport.class, "LBL_PID"); // NOI18N
String HOST = NbBundle.getMessage(OverviewViewSupport.class, "LBL_Host"); // NOI18N
data.append("<b>"+PID+":</b> " + model.getPid() + "<br>"); // NOI18N
data.append("<b>"+HOST+":</b> " + model.getHostName() + "<br>"); // NOI18N
if (model.basicInfoSupported()) {
String MAIN_CLASS = NbBundle.getMessage(OverviewViewSupport.class, "LBL_Main_class"); // NOI18N
String ARGS = NbBundle.getMessage(OverviewViewSupport.class, "LBL_Arguments"); // NOI18N
String JVM = NbBundle.getMessage(OverviewViewSupport.class, "LBL_JVM"); // NOI18N
String JAVA_HOME = NbBundle.getMessage(OverviewViewSupport.class, "LBL_Java_Home"); // NOI18N
String JAVA = NbBundle.getMessage(OverviewViewSupport.class, "LBL_Java"); // NOI18N
String JAVA_VERSION = NbBundle.getMessage(OverviewViewSupport.class, "LBL_Java_Version"); // NOI18N
String JAVA_VENDOR = NbBundle.getMessage(OverviewViewSupport.class, "LBL_Java_Vendor"); // NOI18N
String JVM_FLAGS = NbBundle.getMessage(OverviewViewSupport.class, "LBL_JVM_Flags"); // NOI18N
String HEAP_DUMP_OOME = NbBundle.getMessage(OverviewViewSupport.class, "LBL_Heap_dump_on_OOME"); // NOI18N
data.append("<b>"+MAIN_CLASS+":</b> " + model.getMainClass() + "<br>"); // NOI18N
data.append("<b>"+ARGS+":</b> " + model.getMainArgs() + "<br>"); // NOI18N
data.append("<br>"); // NOI18N
data.append("<b>"+JVM+":</b> " + model.getVmId() + "<br>"); // NOI18N
String javaVersion = model.getJavaVersion();
String javaVendor = model.getJavaVendor();
if (javaVersion != null || javaVendor != null) {
data.append("<b>"+JAVA+":</b>");
if (javaVersion != null) {
data.append(" "+JAVA_VERSION+" " + javaVersion); // NOI18N
}
if (javaVendor != null) {
if (javaVersion != null) data.append(",");
data.append(" "+JAVA_VENDOR+" " + javaVendor); // NOI18N
}
data.append("<br>");
}
data.append("<b>"+JAVA_HOME+":</b> " + model.getJavaHome() + "<br>"); // NOI18N
data.append("<b>"+JVM_FLAGS+":</b> " + model.getJvmFlags() + "<br><br>"); // NOI18N
data.append("<b>"+HEAP_DUMP_OOME+":</b> " + model.oomeEnabled() + "<br>"); // NOI18N
}
return data.toString();
}
}
// --- Snapshots -----------------------------------------------------------
static class SnapshotsViewSupport extends JPanel implements DataChangeListener<Snapshot> {
private static final String LINK_TOGGLE_CATEGORY = "file:/toggle_category"; // NOI18N
private static final String LINK_OPEN_SNAPSHOT = "file:/open_snapshot"; // NOI18N
private DataSource dataSource;
private HTMLTextArea area;
private final Map<Integer, Snapshot> snapshotsMap = new HashMap();
private final Map<String, Boolean> expansionMap = new HashMap();
private boolean standaloneAppSnapshot;
public SnapshotsViewSupport(DataSource dataSource) {
this.dataSource = dataSource;
initComponents();
dataSource.getRepository().addDataChangeListener(this, Snapshot.class);
standaloneAppSnapshot = dataSource.getOwner() == null &&
dataSource instanceof ApplicationSnapshot;
if (standaloneAppSnapshot) {
dataSource.setVisible(false);
DataSource.ROOT.getRepository().addDataSource(dataSource);
}
}
public DataViewComponent.DetailsView getDetailsView() {
return new DataViewComponent.DetailsView(NbBundle.getMessage(OverviewViewSupport.class, "LBL_Saved_data"), null, 10, this, null); // NOI18N
}
private void initComponents() {
setLayout(new BorderLayout());
setOpaque(false);
area = new HTMLTextArea() {
protected void showURL(URL url) {
String link = url.toString();
if (link.startsWith(LINK_TOGGLE_CATEGORY)) {
link = link.substring(LINK_TOGGLE_CATEGORY.length());
toggleExpanded(link);
updateSavedData();
} else if (link.startsWith(LINK_OPEN_SNAPSHOT)) {
link = link.substring(LINK_OPEN_SNAPSHOT.length());
Snapshot s = snapshotsMap.get(Integer.parseInt(link));
if (s != null) DataSourceWindowManager.sharedInstance().openDataSource(s);
}
}
};
updateSavedData();
area.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
add(new ScrollableContainer(area), BorderLayout.CENTER);
}
public void dataChanged(DataChangeEvent<Snapshot> event) {
SwingUtilities.invokeLater(new Runnable() {
public void run() { updateSavedData(); }
});
}
void removed() {
dataSource.getRepository().removeDataChangeListener(this);
if (standaloneAppSnapshot)
DataSource.ROOT.getRepository().removeDataSource(dataSource);
}
private void updateSavedData() {
snapshotsMap.clear();
StringBuilder data = new StringBuilder();
List<SnapshotCategory> snapshotCategories = RegisteredSnapshotCategories.sharedInstance().getVisibleCategories();
for (SnapshotCategory category : snapshotCategories) {
Set<Snapshot> snapshots = dataSource.getRepository().getDataSources(category.getType());
if (snapshots.isEmpty()) {
data.append("<b>" + category.getName() + ":</b> " + snapshots.size() + "<br>"); // NOI18N
} else {
String categoryName = category.getName();
data.append("<b>" + categoryName + ":</b> <a href='" + (LINK_TOGGLE_CATEGORY + categoryName) + "'>" + snapshots.size() + "</a><br>"); // NOI18N
if (isExpanded(categoryName)) {
List<DataSourceDescriptor> descriptors = new ArrayList();
Map<DataSourceDescriptor, Snapshot> dataSources = new HashMap();
for (Snapshot s : snapshots) {
DataSourceDescriptor dsd = DataSourceDescriptorFactory.getDescriptor(s);
descriptors.add(dsd);
dataSources.put(dsd, s);
}
Collections.sort(descriptors, Positionable.STRONG_COMPARATOR);
int size = snapshotsMap.size();
for (int i = 0; i < descriptors.size(); i++) {
DataSourceDescriptor dsd = descriptors.get(i);
Snapshot s = dataSources.get(dsd);
snapshotsMap.put(i + size, s);
data.append(" <a href='" + LINK_OPEN_SNAPSHOT + (i + size) + "'>" + dsd.getName() + "</a><br>"); // NOI18N
}
data.append("<br>"); // NOI18N
}
}
}
area.setText("<nobr>" + data.toString() + "</nobr>"); // NOI18N
}
private boolean isExpanded(String categoryName) {
Boolean expanded = expansionMap.get(categoryName);
if (expanded == null) {
expanded = standaloneAppSnapshot;
expansionMap.put(categoryName, expanded);
}
return expanded.booleanValue();
}
private void toggleExpanded(String categoryName) {
expansionMap.put(categoryName, !isExpanded(categoryName));
}
}
// --- JVM arguments -------------------------------------------------------
static class JVMArgumentsViewSupport extends JPanel {
public JVMArgumentsViewSupport(String jvmargs) {
initComponents(jvmargs);
}
public DataViewComponent.DetailsView getDetailsView() {
return new DataViewComponent.DetailsView(NbBundle.getMessage(OverviewViewSupport.class, "LBL_JVM_arguments"), null, 10, this, null); // NOI18N
}
private void initComponents(String jvmargs) {
setLayout(new BorderLayout());
setOpaque(false);
JComponent contents;
if (jvmargs != null) {
HTMLTextArea area = new HTMLTextArea("<nobr>" + jvmargs + "</nobr>"); // NOI18N
area.setCaretPosition(0);
area.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
contents = area;
} else {
contents = new NotSupportedDisplayer(NotSupportedDisplayer.JVM);
}
add(new ScrollableContainer(contents), BorderLayout.CENTER);
}
}
// --- System properties ---------------------------------------------------
static class SystemPropertiesViewSupport extends JPanel {
public SystemPropertiesViewSupport(String properties) {
initComponents(properties);
}
public DataViewComponent.DetailsView getDetailsView() {
return new DataViewComponent.DetailsView(NbBundle.getMessage(OverviewViewSupport.class, "LBL_System_properties"), null, 20, this, null); // NOI18N
}
private void initComponents(String properties) {
setLayout(new BorderLayout());
setOpaque(false);
JComponent contents;
if (properties != null) {
HTMLTextArea area = new HTMLTextArea("<nobr>" + properties + "</nobr>"); // NOI18N
area.setCaretPosition(0);
area.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
contents = area;
} else {
contents = new NotSupportedDisplayer(NotSupportedDisplayer.JVM);
}
add(new ScrollableContainer(contents), BorderLayout.CENTER);
}
}
}