Mercurial > hg > release > heapstats-1.0
changeset 14:27a3ec638eaa
Bug 1475: Some codes' line feed code are CRLF(DOS).
reviewed-by: yasuenag
author | "KUBOTA Yuji <kubota.yuji@lab.ntt.co.jp>" |
---|---|
date | Mon, 24 Jun 2013 18:06:21 -0700 |
parents | 1d573d30fe94 |
children | 6d475889590a |
files | agent/src/jniZipArchiver.hpp analyzer/filterDefine.xsd analyzer/src/jp/co/ntt/oss/heapstats/container/ThreadData.java analyzer/src/jp/co/ntt/oss/heapstats/gui/BrowseButton.java analyzer/src/jp/co/ntt/oss/heapstats/gui/DiffDialog.java analyzer/src/jp/co/ntt/oss/heapstats/gui/FindDialog.java analyzer/src/jp/co/ntt/oss/heapstats/gui/GCDialog.java analyzer/src/jp/co/ntt/oss/heapstats/gui/GuiCommon.java analyzer/src/jp/co/ntt/oss/heapstats/gui/LogDetailDialog.java analyzer/src/jp/co/ntt/oss/heapstats/gui/ResourceDialog.java analyzer/src/jp/co/ntt/oss/heapstats/gui/SelectLogfiles.java analyzer/src/jp/co/ntt/oss/heapstats/gui/SnapShotDialog.java |
diffstat | 12 files changed, 5751 insertions(+), 5751 deletions(-) [+] |
line wrap: on
line diff
--- a/agent/src/jniZipArchiver.hpp Mon Jun 24 11:42:50 2013 +0900 +++ b/agent/src/jniZipArchiver.hpp Mon Jun 24 18:06:21 2013 -0700 @@ -24,7 +24,7 @@ #include <jni.h> #include <jvmti.h> - + #include "archiveMaker.hpp" #include "util.hpp"
--- a/analyzer/filterDefine.xsd Mon Jun 24 11:42:50 2013 +0900 +++ b/analyzer/filterDefine.xsd Mon Jun 24 18:06:21 2013 -0700 @@ -1,27 +1,27 @@ -<?xml version="1.0" encoding="UTF-8"?> -<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> - <xsd:element name="filters" type="filterstype"> - <xsd:unique name="filtername"> - <xsd:selector xpath="filter" /> - <xsd:field xpath="@name" /> - </xsd:unique> - </xsd:element> - <xsd:complexType name="filterstype"> - <xsd:sequence> - <xsd:element name="filter" type="filtertype" maxOccurs="unbounded" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="filtertype"> - <xsd:sequence> - <xsd:element name="visible" type="xsd:boolean" /> - <xsd:element name="classes"> - <xsd:complexType> - <xsd:sequence> - <xsd:element maxOccurs="unbounded" name="name" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - </xsd:sequence> - <xsd:attribute name="name" type="xsd:string" use="required" /> - </xsd:complexType> -</xsd:schema> +<?xml version="1.0" encoding="UTF-8"?> +<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> + <xsd:element name="filters" type="filterstype"> + <xsd:unique name="filtername"> + <xsd:selector xpath="filter" /> + <xsd:field xpath="@name" /> + </xsd:unique> + </xsd:element> + <xsd:complexType name="filterstype"> + <xsd:sequence> + <xsd:element name="filter" type="filtertype" maxOccurs="unbounded" /> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="filtertype"> + <xsd:sequence> + <xsd:element name="visible" type="xsd:boolean" /> + <xsd:element name="classes"> + <xsd:complexType> + <xsd:sequence> + <xsd:element maxOccurs="unbounded" name="name" type="xsd:string" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> +</xsd:schema>
--- a/analyzer/src/jp/co/ntt/oss/heapstats/container/ThreadData.java Mon Jun 24 11:42:50 2013 +0900 +++ b/analyzer/src/jp/co/ntt/oss/heapstats/container/ThreadData.java Mon Jun 24 18:06:21 2013 -0700 @@ -1,172 +1,172 @@ -/* - * ThreadData.java - * Created on 2012/05/24 - * - * Copyright (C) 2011-2013 Nippon Telegraph and Telephone Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program 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 for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ -package jp.co.ntt.oss.heapstats.container; - -import java.io.Serializable; - -/** - * implements {@link Serializable}<br> - * <br> - * Contains information about the thread. - */ -public class ThreadData implements - Serializable { - /** serialVersionUID. */ - private static final long serialVersionUID = 3795657965056209363L; - - /** Class name. */ - private String className; - - /** Method name. */ - private String methodName; - - /** thread name. */ - private String threadName; - - /** Waiting to lock object has been retrieved. */ - private String waitLock; - - /** Thread that owns the lock object has been waiting for acquisition. */ - private String waitThread; - - /** lock object or thread name. */ - private String lockThread; - - /** - * Create a ThreadData. - */ - public ThreadData() { - className = ""; - threadName = ""; - waitLock = ""; - waitThread = ""; - lockThread = ""; - } - - /** - * Return the Class Name. - * - * @return Return the Class Name - */ - public final String getClassName() { - return className; - } - - /** - * Sets the Class Name. - * - * @param value Sets the Class Name - */ - public final void setClassName(final String value) { - this.className = value; - } - - /** - * Return the Method Name. - * - * @return Return the Method Name - */ - public final String getMethodName() { - return methodName; - } - - /** - * Sets the Method Name - * - * @param value Sets the Method Name - */ - public final void setMethodName(String value) { - this.methodName = value; - } - - /** - * Return the thread name. - * - * @return Return the thread name - */ - public final String getThreadName() { - return threadName; - } - - /** - * Sets the thread name. - * - * @param value Sets the thread name - */ - public final void setThreadName(final String value) { - this.threadName = value; - } - - /** - * Return the wait lock object. - * - * @return Return the wait lock object - */ - public final String getWaitLock() { - return waitLock; - } - - /** - * Sets the wait lock object. - * - * @param value Sets the wait lock object - */ - public final void setWaitLock(final String value) { - this.waitLock = value; - } - - /** - * Return the wait thread name. - * - * @return Return the wait thread name - */ - public final String getWaitThread() { - return waitThread; - } - - /** - * Sets the wait thread name. - * - * @param value Sets the wait thread name - */ - public final void setWaitThread(final String value) { - this.waitThread = value; - } - - /** - * Return the lock thread name or lock object. - * - * @return Return the lock thread name or lock object - */ - public final String getLockThread() { - return lockThread; - } - - /** - * Sets the lock thread name or lock object. - * - * @param value Sets the lock thread name or lock object - */ - public final void setLockThread(final String value) { - this.lockThread = value; - } -} +/* + * ThreadData.java + * Created on 2012/05/24 + * + * Copyright (C) 2011-2013 Nippon Telegraph and Telephone Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ +package jp.co.ntt.oss.heapstats.container; + +import java.io.Serializable; + +/** + * implements {@link Serializable}<br> + * <br> + * Contains information about the thread. + */ +public class ThreadData implements + Serializable { + /** serialVersionUID. */ + private static final long serialVersionUID = 3795657965056209363L; + + /** Class name. */ + private String className; + + /** Method name. */ + private String methodName; + + /** thread name. */ + private String threadName; + + /** Waiting to lock object has been retrieved. */ + private String waitLock; + + /** Thread that owns the lock object has been waiting for acquisition. */ + private String waitThread; + + /** lock object or thread name. */ + private String lockThread; + + /** + * Create a ThreadData. + */ + public ThreadData() { + className = ""; + threadName = ""; + waitLock = ""; + waitThread = ""; + lockThread = ""; + } + + /** + * Return the Class Name. + * + * @return Return the Class Name + */ + public final String getClassName() { + return className; + } + + /** + * Sets the Class Name. + * + * @param value Sets the Class Name + */ + public final void setClassName(final String value) { + this.className = value; + } + + /** + * Return the Method Name. + * + * @return Return the Method Name + */ + public final String getMethodName() { + return methodName; + } + + /** + * Sets the Method Name + * + * @param value Sets the Method Name + */ + public final void setMethodName(String value) { + this.methodName = value; + } + + /** + * Return the thread name. + * + * @return Return the thread name + */ + public final String getThreadName() { + return threadName; + } + + /** + * Sets the thread name. + * + * @param value Sets the thread name + */ + public final void setThreadName(final String value) { + this.threadName = value; + } + + /** + * Return the wait lock object. + * + * @return Return the wait lock object + */ + public final String getWaitLock() { + return waitLock; + } + + /** + * Sets the wait lock object. + * + * @param value Sets the wait lock object + */ + public final void setWaitLock(final String value) { + this.waitLock = value; + } + + /** + * Return the wait thread name. + * + * @return Return the wait thread name + */ + public final String getWaitThread() { + return waitThread; + } + + /** + * Sets the wait thread name. + * + * @param value Sets the wait thread name + */ + public final void setWaitThread(final String value) { + this.waitThread = value; + } + + /** + * Return the lock thread name or lock object. + * + * @return Return the lock thread name or lock object + */ + public final String getLockThread() { + return lockThread; + } + + /** + * Sets the lock thread name or lock object. + * + * @param value Sets the lock thread name or lock object + */ + public final void setLockThread(final String value) { + this.lockThread = value; + } +}
--- a/analyzer/src/jp/co/ntt/oss/heapstats/gui/BrowseButton.java Mon Jun 24 11:42:50 2013 +0900 +++ b/analyzer/src/jp/co/ntt/oss/heapstats/gui/BrowseButton.java Mon Jun 24 18:06:21 2013 -0700 @@ -1,244 +1,244 @@ -/* - * BrowseButton.java - * Created on 2012/01/24 - * - * Copyright (C) 2011-2013 Nippon Telegraph and Telephone Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program 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 for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ -package jp.co.ntt.oss.heapstats.gui; - -import java.awt.Component; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.util.EventObject; - -import javax.swing.AbstractCellEditor; -import javax.swing.BorderFactory; -import javax.swing.JButton; -import javax.swing.JOptionPane; -import javax.swing.JTable; -import javax.swing.JTextArea; -import javax.swing.event.CellEditorListener; -import javax.swing.table.TableCellEditor; -import javax.swing.table.TableCellRenderer; - -/** - * extends {@link AbstractCellEditor}<br> - * implements {@link TableCellEditor}, {@link TableCellRenderer}<br> - * <br> - * Displayed in a text file data or contents of the specified line. - */ -public class BrowseButton extends AbstractCellEditor implements - TableCellEditor, - TableCellRenderer, - ActionListener { - /** serialVersionUID. */ - private static final long serialVersionUID = -4223033654188094768L; - - /** The name of a reference button. */ - private static final String BUTTON_NAME = "..."; - - private static final int COL_IDX_PATH = 3; - - /** Table to display the details of the log. */ - private JTable itemEntries; - - /** Text area that displays the log information for the specified items. */ - private JTextArea detail; - - /** The reference button. */ - private JButton browse; - - /** LogDetail Data. */ - private LogDetailDialog detailDlg; - - /** - * Create a Browse button to put on the table. - * - * @param parent Log Detail Data - * @param table Table to display the details of the log - * @param area Text area that displays the log information for the specified - * items - */ - public BrowseButton(final LogDetailDialog parent, final JTable table, - final JTextArea area) { - detailDlg = parent; - itemEntries = table; - detail = area; - - browse = new JButton(BUTTON_NAME) { - /** serialVersionUID. */ - private static final long serialVersionUID = -6292696235280698041L; - - @Override - public void updateUI() { - super.updateUI(); - setBorder(BorderFactory.createEmptyBorder()); - setFocusable(false); - setRolloverEnabled(false); - setText(BUTTON_NAME); - } - }; - - browse.addActionListener(this); - } - - @Override - public final void addCellEditorListener(final CellEditorListener l) { - listenerList.add(CellEditorListener.class, l); - } - - @Override - public final void cancelCellEditing() { - fireEditingCanceled(); - } - - @Override - public final Object getCellEditorValue() { - return browse.getText(); - } - - @Override - public final boolean isCellEditable(final EventObject l) { - return true; - } - - @Override - public final void removeCellEditorListener(final CellEditorListener l) { - listenerList.remove(CellEditorListener.class, l); - } - - /** - * Returns true if the editing cell should be selected, false otherwise. - * - * @param anEvent the event the editor should use to start editing - * @return Returns false. - */ - @Override - public final boolean shouldSelectCell(final EventObject anEvent) { - return false; - } - - @Override - public final boolean stopCellEditing() { - fireEditingStopped(); - return true; - } - - @Override - public final Component getTableCellRendererComponent(final JTable table, - final Object value, final boolean isSelected, - final boolean hasFocus, final int row, final int column) { - return browse; - } - - @Override - public final Component getTableCellEditorComponent(final JTable table, - final Object value, final boolean isSelected, final int row, - final int column) { - return browse; - } - - @Override - public final void actionPerformed(final ActionEvent e) { - int row = itemEntries.convertRowIndexToModel(itemEntries - .getEditingRow()); - detail.setText(""); - detail.append(String.valueOf(itemEntries.getValueAt(row, 0))); - detail.append("\n\n"); - - Object path = itemEntries.getValueAt(row, COL_IDX_PATH); - if (path == null || path.equals(BUTTON_NAME)) { - detail.append(String.valueOf(itemEntries.getValueAt(row, 1))); - } else { - loadFile(path); - } - - detail.setCaretPosition(0); - - fireEditingCanceled(); - } - - /** - * Returns the contents of the file specified. - * - * @param path Absolute file path - */ - private void loadFile(final Object path) { - BufferedReader read = null; - // StringBuilder sb = new StringBuilder(); - String[] pathList = String.valueOf(path).split( - GuiCommon.SPLIT_CHARACTER); - - File file = null; - try { - for (String tmp : pathList) { - file = new File(tmp); - read = new BufferedReader(new FileReader(file)); - - String line = read.readLine(); - - while (line != null) { - // Converted to blank a null character. - int ind = line.indexOf("\0"); - int prev = 0; - while (ind > 0 && ind < line.length()) { - detail.append(line.substring(prev, ind)); - detail.append(" "); - prev = ind + 1; - ind = line.indexOf("\0", prev); - } - - if (prev == 0) { - detail.append(line); - } - - detail.append("\n"); - line = read.readLine(); - } - - if (read != null) { - read.close(); - } - } - } catch (Throwable e) { - if (file != null) { - GuiCommon.showMessage(detailDlg, GuiCommon.BASEE08, - file.getName(), JOptionPane.ERROR_MESSAGE); - } else { - GuiCommon.showMessage(detailDlg, GuiCommon.BASEE08, - String.valueOf(path), JOptionPane.ERROR_MESSAGE); - } - e.printStackTrace(); - } finally { - try { - if (read != null) { - read.close(); - } - } catch (IOException e) { - GuiCommon.showMessage(detailDlg, GuiCommon.BASEE08, - file.getName(), JOptionPane.ERROR_MESSAGE); - e.printStackTrace(); - } - } - } - -} +/* + * BrowseButton.java + * Created on 2012/01/24 + * + * Copyright (C) 2011-2013 Nippon Telegraph and Telephone Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ +package jp.co.ntt.oss.heapstats.gui; + +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.EventObject; + +import javax.swing.AbstractCellEditor; +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JOptionPane; +import javax.swing.JTable; +import javax.swing.JTextArea; +import javax.swing.event.CellEditorListener; +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableCellRenderer; + +/** + * extends {@link AbstractCellEditor}<br> + * implements {@link TableCellEditor}, {@link TableCellRenderer}<br> + * <br> + * Displayed in a text file data or contents of the specified line. + */ +public class BrowseButton extends AbstractCellEditor implements + TableCellEditor, + TableCellRenderer, + ActionListener { + /** serialVersionUID. */ + private static final long serialVersionUID = -4223033654188094768L; + + /** The name of a reference button. */ + private static final String BUTTON_NAME = "..."; + + private static final int COL_IDX_PATH = 3; + + /** Table to display the details of the log. */ + private JTable itemEntries; + + /** Text area that displays the log information for the specified items. */ + private JTextArea detail; + + /** The reference button. */ + private JButton browse; + + /** LogDetail Data. */ + private LogDetailDialog detailDlg; + + /** + * Create a Browse button to put on the table. + * + * @param parent Log Detail Data + * @param table Table to display the details of the log + * @param area Text area that displays the log information for the specified + * items + */ + public BrowseButton(final LogDetailDialog parent, final JTable table, + final JTextArea area) { + detailDlg = parent; + itemEntries = table; + detail = area; + + browse = new JButton(BUTTON_NAME) { + /** serialVersionUID. */ + private static final long serialVersionUID = -6292696235280698041L; + + @Override + public void updateUI() { + super.updateUI(); + setBorder(BorderFactory.createEmptyBorder()); + setFocusable(false); + setRolloverEnabled(false); + setText(BUTTON_NAME); + } + }; + + browse.addActionListener(this); + } + + @Override + public final void addCellEditorListener(final CellEditorListener l) { + listenerList.add(CellEditorListener.class, l); + } + + @Override + public final void cancelCellEditing() { + fireEditingCanceled(); + } + + @Override + public final Object getCellEditorValue() { + return browse.getText(); + } + + @Override + public final boolean isCellEditable(final EventObject l) { + return true; + } + + @Override + public final void removeCellEditorListener(final CellEditorListener l) { + listenerList.remove(CellEditorListener.class, l); + } + + /** + * Returns true if the editing cell should be selected, false otherwise. + * + * @param anEvent the event the editor should use to start editing + * @return Returns false. + */ + @Override + public final boolean shouldSelectCell(final EventObject anEvent) { + return false; + } + + @Override + public final boolean stopCellEditing() { + fireEditingStopped(); + return true; + } + + @Override + public final Component getTableCellRendererComponent(final JTable table, + final Object value, final boolean isSelected, + final boolean hasFocus, final int row, final int column) { + return browse; + } + + @Override + public final Component getTableCellEditorComponent(final JTable table, + final Object value, final boolean isSelected, final int row, + final int column) { + return browse; + } + + @Override + public final void actionPerformed(final ActionEvent e) { + int row = itemEntries.convertRowIndexToModel(itemEntries + .getEditingRow()); + detail.setText(""); + detail.append(String.valueOf(itemEntries.getValueAt(row, 0))); + detail.append("\n\n"); + + Object path = itemEntries.getValueAt(row, COL_IDX_PATH); + if (path == null || path.equals(BUTTON_NAME)) { + detail.append(String.valueOf(itemEntries.getValueAt(row, 1))); + } else { + loadFile(path); + } + + detail.setCaretPosition(0); + + fireEditingCanceled(); + } + + /** + * Returns the contents of the file specified. + * + * @param path Absolute file path + */ + private void loadFile(final Object path) { + BufferedReader read = null; + // StringBuilder sb = new StringBuilder(); + String[] pathList = String.valueOf(path).split( + GuiCommon.SPLIT_CHARACTER); + + File file = null; + try { + for (String tmp : pathList) { + file = new File(tmp); + read = new BufferedReader(new FileReader(file)); + + String line = read.readLine(); + + while (line != null) { + // Converted to blank a null character. + int ind = line.indexOf("\0"); + int prev = 0; + while (ind > 0 && ind < line.length()) { + detail.append(line.substring(prev, ind)); + detail.append(" "); + prev = ind + 1; + ind = line.indexOf("\0", prev); + } + + if (prev == 0) { + detail.append(line); + } + + detail.append("\n"); + line = read.readLine(); + } + + if (read != null) { + read.close(); + } + } + } catch (Throwable e) { + if (file != null) { + GuiCommon.showMessage(detailDlg, GuiCommon.BASEE08, + file.getName(), JOptionPane.ERROR_MESSAGE); + } else { + GuiCommon.showMessage(detailDlg, GuiCommon.BASEE08, + String.valueOf(path), JOptionPane.ERROR_MESSAGE); + } + e.printStackTrace(); + } finally { + try { + if (read != null) { + read.close(); + } + } catch (IOException e) { + GuiCommon.showMessage(detailDlg, GuiCommon.BASEE08, + file.getName(), JOptionPane.ERROR_MESSAGE); + e.printStackTrace(); + } + } + } + +}
--- a/analyzer/src/jp/co/ntt/oss/heapstats/gui/DiffDialog.java Mon Jun 24 11:42:50 2013 +0900 +++ b/analyzer/src/jp/co/ntt/oss/heapstats/gui/DiffDialog.java Mon Jun 24 18:06:21 2013 -0700 @@ -1,1074 +1,1074 @@ -/* - * DiffDialog.java - * Created on 2011/10/13 - * - * Copyright (C) 2011-2013 Nippon Telegraph and Telephone Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program 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 for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -package jp.co.ntt.oss.heapstats.gui; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.Cursor; -import java.awt.Dimension; -import java.awt.FlowLayout; -import java.awt.Paint; -import java.awt.event.ActionEvent; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.swing.BorderFactory; -import javax.swing.Box; -import javax.swing.BoxLayout; -import javax.swing.DefaultListModel; -import javax.swing.JButton; -import javax.swing.JDialog; -import javax.swing.JFileChooser; -import javax.swing.JLabel; -import javax.swing.JList; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JSplitPane; -import javax.swing.JTable; -import javax.swing.RowSorter.SortKey; -import javax.swing.SortOrder; -import javax.swing.SwingWorker; -import javax.swing.filechooser.FileNameExtensionFilter; -import javax.swing.table.TableCellRenderer; -import javax.swing.table.TableColumnModel; -import javax.swing.table.TableModel; -import javax.swing.table.TableRowSorter; - -import jp.co.ntt.oss.heapstats.container.MapKey; -import jp.co.ntt.oss.heapstats.container.ObjectData; -import jp.co.ntt.oss.heapstats.container.PackageFilter; -import jp.co.ntt.oss.heapstats.container.SnapShot; -import jp.co.ntt.oss.heapstats.gui.graph.GraphColorHelper; -import jp.co.ntt.oss.heapstats.gui.snapshot.PackageFilterReader; -import jp.co.ntt.oss.heapstats.gui.snapshot.SnapShotHelper; -import jp.co.ntt.oss.heapstats.gui.snapshot.SnapShotReader; - -import org.jfree.chart.ChartFactory; -import org.jfree.chart.ChartPanel; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.axis.CategoryAxis; -import org.jfree.chart.axis.CategoryLabelPositions; -import org.jfree.chart.axis.NumberAxis; -import org.jfree.chart.axis.ValueAxis; -import org.jfree.chart.plot.CategoryPlot; -import org.jfree.chart.plot.PlotOrientation; -import org.jfree.chart.renderer.category.LineAndShapeRenderer; -import org.jfree.data.category.DefaultCategoryDataset; - -/** - * extends {@link JDialog}<br> - * implements {@link PropertyChangeListener}<br> - * <br> - * Delta Index chart, draw a stacked heap usage chart. In addition, articles can - * be done by filter class. - */ -public class DiffDialog extends JDialog implements - PropertyChangeListener { - /** serialVersionUID. */ - private static final long serialVersionUID = 31766154511197856L; - - /** Angle of the axis labels. */ - private static final double ANGLE = 6.0; - - /** The button name for choosing all the classes for search. */ - private static final String SELECT_BUTTON_NAME = " Select All "; - - /** A SnapShot Dialog. */ - private SnapShotDialog ssDlg; - - /** Mainframe heapstats. */ - private GUIMain guimain; - - /** Main Component. */ - private JSplitPane comp; - - /** Delta data information display unit. */ - private Box deltaUnit = Box.createVerticalBox(); - - /** Ranking Chart Panel. */ - private ExpansionContractionPanel rank; - - /** Heap Usage Chart Panel. */ - private ExpansionContractionPanel usage; - - /** Objects List. */ - private ExpansionContractionPanel objList; - - /** Objects List DefaultTableModel. */ - private DiffEntriesModel diffEntriesModel; - - /** Objects List Table. */ - private JTable diffEntries; - - /** Class Filter TableModel. */ - private FilterEntriesModel filterEntriesModel; - - /** Class Filter Table. */ - private JTable filterEntries; - - /** Class Filter OK Button. */ - private JButton addOkbtn; - - /** Class Filter Clean Button. */ - private JButton clearBtn; - - /** Class Filter Information. */ - private PackageFilter packageFilter; - - /** Regular expression. */ - private List<Pattern> filterList; - - /** Filter Results Class List. */ - private Object[] searchClass; - - /** Class Search List. */ - private JList classList; - - /** Class Search. */ - private SearchJTextField searchText; - - /** Class Search OK Button. */ - private JButton searchOkbtn; - - /** Class Search Clear Button. */ - private JButton searchClearbtn; - - /** Select button. */ - private JButton selectBtn; - - /** Sort Button. instance */ - private JButton insBtn; - - /** Sort Button. heap size */ - private JButton sizeBtn; - - /** A class list search paths. */ - private Set<String> nameList; - - /** Offsets Key is Date. Data is file position and SnapShotReader. */ - private Map<String, List<Object>> offsets; - - /** the List is file position and SnapShotReader. */ - private List<List<Object>> diffOffsets; - - /** ProgressBar. */ - private HeapProgressBar progressBar; - - /** The SwingWorker for drawing graphs. */ - private DiffWorker worker; - - /** The panel of Ranking Chart. */ - private ChartPanel rankChart; - - /** The panel of Usage Chart. */ - private ChartPanel usageChart; - - /** - * Creates a modeless dialog with the specified Dialog as its owner. - * - * @param owner the owner Dialog from which the dialog is displayed or null - * if this dialog has no owner - * @param dialog the snapshot dialog - */ - public DiffDialog(final GUIMain owner, final SnapShotDialog dialog) { - super(owner); - - guimain = owner; - ssDlg = dialog; - rank = null; - usage = null; - objList = null; - comp = null; - searchClass = null; - filterList = new ArrayList<Pattern>(); - packageFilter = new PackageFilter(); - nameList = new HashSet<String>(); - - setTitle(GuiCommon.getResources().getString(GuiCommon.TAB_TITLE_DELA)); - setSize(GuiCommon.DEFAULT_DIALOG_WIDTH, GuiCommon.DEFAULT_DIALOG_HEIGHT); - setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); - setModal(false); - - addComponent(); - setLocationByPlatform(true); - } - - /** - * Create components to draw on the screen. - */ - private void addComponent() { - Box search = Box.createVerticalBox(); - search.setBorder(BorderFactory.createEmptyBorder(GuiCommon.BORDER_SIZE, - GuiCommon.BORDER_SIZE, GuiCommon.BORDER_SIZE, - GuiCommon.BORDER_SIZE)); - - JPanel diffPanel = new JPanel(); - diffPanel.setLayout(new BorderLayout()); - deltaUnit.setBorder(BorderFactory.createEmptyBorder( - GuiCommon.BORDER_SIZE, GuiCommon.BORDER_SIZE, - GuiCommon.BORDER_SIZE, GuiCommon.BORDER_SIZE)); - - comp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, search, diffPanel); - comp.setOneTouchExpandable(true); - - search.add(Box.createVerticalStrut(GuiCommon.BORDER_SIZE)); - search.add(addFilterComponent()); - search.add(Box.createVerticalStrut(GuiCommon.BORDER_SIZE)); - search.add(addIncrementComponent()); - - diffPanel.add(deltaUnit); - - diffEntriesModel = new DiffEntriesModel(); - diffEntries = new JTable(diffEntriesModel) { - /** serialVersionUID. */ - private static final long serialVersionUID = -925317579655004381L; - - @Override - public Component prepareRenderer(final TableCellRenderer tcr, - final int row, final int column) { - Component retVal = super.prepareRenderer(tcr, row, column); - - retVal.setForeground(getForeground()); - Paint bgPaint = GraphColorHelper.getColor((String) getValueAt( - row, 1)); - if (bgPaint != null && column == 0) { - retVal.setBackground((Color) bgPaint); - } else { - retVal.setBackground(Color.WHITE); - } - return retVal; - } - }; - - TableColumnModel model = diffEntries.getColumnModel(); - model.getColumn(0).setPreferredWidth(GuiCommon.COL_SIZE_COLOR); - model.getColumn(1).setPreferredWidth(GuiCommon.COL_SIZE_CLASSNAME); - - rank = new ExpansionContractionPanel(GuiCommon.getResources() - .getString(GuiCommon.TITLE_SIZE_DELTE)); - usage = new ExpansionContractionPanel(GuiCommon.getResources() - .getString(GuiCommon.TITLE_SIZE_AREA)); - objList = new ExpansionContractionPanel(GuiCommon.getResources() - .getString(GuiCommon.TITLE_OBJECTLIST)); - } - - /** - * Creates a Class filter component. - * - * @return Return the Filter ExpansionContractionPanel - */ - private JPanel addFilterComponent() { - // Class Filter - ExpansionContractionPanel filterMain = new ExpansionContractionPanel( - GuiCommon.getResources().getString( - GuiCommon.CLASS_FILTER_LABEL_TITLE)); - JPanel classPanel = new JPanel(new BorderLayout()); - filterMain.setComponent(classPanel, true); - classPanel.setBackground(Color.WHITE); - - JPanel addPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); - addPanel.setBackground(Color.WHITE); - - JButton addFilter = new JButton(GuiCommon.getResources().getString( - GuiCommon.CLASS_FILTER_ADD)); - addFilter.setPreferredSize(new Dimension(120, 20)); - addFilter.addActionListener(guimain); - - addPanel.add(addFilter); - - filterEntriesModel = new FilterEntriesModel(); - filterEntries = new JTable(filterEntriesModel); - - JScrollPane pkgScroll = new JScrollPane(); - pkgScroll.getViewport().setView(filterEntries); - - JPanel okPanel = new JPanel(); - okPanel.setLayout(new BoxLayout(okPanel, BoxLayout.X_AXIS)); - okPanel.setBackground(Color.WHITE); - okPanel.add(Box.createVerticalStrut(GuiCommon.BORDER_SIZE)); - - clearBtn = new JButton("Clear"); - clearBtn.setMaximumSize(new Dimension(70, 20)); - clearBtn.addActionListener(guimain); - okPanel.add(clearBtn); - okPanel.add(new JLabel(" ")); - - addOkbtn = new JButton("OK"); - addOkbtn.setMaximumSize(new Dimension(60, 20)); - addOkbtn.addActionListener(guimain); - - okPanel.add(addOkbtn); - - TableColumnModel model = filterEntries.getColumnModel(); - model.getColumn(0).setMaxWidth(50); - - classPanel.add(BorderLayout.NORTH, addPanel); - classPanel.add(BorderLayout.CENTER, pkgScroll); - classPanel.add(BorderLayout.SOUTH, okPanel); - - return filterMain; - } - - /** - * Creates a Class search component. - * - * @return Return the Incremental Search Component - */ - private JPanel addIncrementComponent() { - // Incremental Search - ExpansionContractionPanel searchMain = new ExpansionContractionPanel( - GuiCommon.getResources().getString( - GuiCommon.CLASS_SEARCH_LABEL_TITLE)); - JPanel increPanel = new JPanel(new BorderLayout()); - increPanel.setBackground(Color.WHITE); - - searchMain.setComponent(increPanel, true); - JPanel okPanel = new JPanel(); - okPanel.setLayout(new BoxLayout(okPanel, BoxLayout.X_AXIS)); - okPanel.setBackground(Color.WHITE); - - searchClearbtn = new JButton("Clear"); - searchClearbtn.setMaximumSize(new Dimension(70, 20)); - searchClearbtn.addActionListener(guimain); - searchOkbtn = new JButton("OK"); - searchOkbtn.setMaximumSize(new Dimension(60, 20)); - searchOkbtn.addActionListener(guimain); - selectBtn = new JButton(SELECT_BUTTON_NAME); - selectBtn.setMinimumSize(new Dimension(110, 20)); - selectBtn.setMaximumSize(new Dimension(110, 20)); - selectBtn.addActionListener(guimain); - - okPanel.add(selectBtn); - okPanel.add(Box.createVerticalStrut(GuiCommon.BORDER_SIZE)); - okPanel.add(new JLabel(" ")); - okPanel.add(searchClearbtn); - okPanel.add(new JLabel(" ")); - okPanel.add(searchOkbtn); - - DefaultListModel classModel = new DefaultListModel(); - classList = new JList(classModel); - classList.setVisibleRowCount(50); - JScrollPane listScroll = new JScrollPane(); - listScroll.getViewport().setView(classList); - - searchText = new SearchJTextField(0, classModel); - - // add(p1); - increPanel.add(BorderLayout.NORTH, searchText); - increPanel.add(BorderLayout.CENTER, listScroll); - increPanel.add(BorderLayout.SOUTH, okPanel); - - return searchMain; - } - - /** - * Create an exclusion list for the class. - */ - private void createFilterList() { - // Class Filter - filterList.clear(); - for (int i = 0; i < filterEntriesModel.getRowCount(); i++) { - if ((Boolean) filterEntriesModel.getValueAt(i, 0)) { - List<String> datas = packageFilter - .get((String) filterEntriesModel.getValueAt(i, 1)); - for (int j = 1; j < datas.size(); j++) { - StringBuilder buf = new StringBuilder(); - buf.append("(^\\W*|L|\\W*L)?"); - if (GuiCommon.getClassRename()) { - buf.append(datas.get(j).replace("\\", ".")); - } else { - buf.append(datas.get(j)); - if ((datas.get(j).lastIndexOf(";") == -1) - && (datas.get(j).lastIndexOf("*") == -1)) { - buf.append("(;)?"); - } - } - filterList.add(Pattern.compile(buf.toString(), - Pattern.CASE_INSENSITIVE)); - } - } - } - } - - /** - * Filter class to return a list of articles ObjectData made. - * - * @param diff Class Map to be filtered - * @return Return the class filtered list - */ - private List<ObjectData> filterClassMap(final Map<Long, ObjectData> diff) { - ObjectData[] list = new ObjectData[diff.size()]; - - // Start Filter - int i = 0; - for (Map.Entry<Long, ObjectData> elmt : diff.entrySet()) { - list[i++] = elmt.getValue(); - } - - return startFilter(list); - } - - /** - * Filter class to return a list of articles ObjectData made. - * - * @param list ObjectData - * @return Return the ObjectData filtered list - */ - private List<ObjectData> startFilter(final ObjectData[] list) { - List<ObjectData> tmpList = new ArrayList<ObjectData>(); - List<ObjectData> viewSet = new ArrayList<ObjectData>(); - - // Start Filter - for (ObjectData elmt : list) { - boolean match = false; - for (Pattern ptn : filterList) { - Matcher matcher = ptn.matcher(elmt.getName()); - if (matcher.matches()) { - match = true; - break; - } - } - - if (!match) { - // Matches or, when there is no filter - tmpList.add(elmt); - } - } - - // Class Search - if (searchClass != null && searchClass.length > 0) { - for (ObjectData data : tmpList) { - for (Object path : searchClass) { - if (data.getName().equals(path)) { - viewSet.add(data); - } - } - } - } else { - // when there is no filter - viewSet.addAll(tmpList); - } - return viewSet; - } - - /** - * Add a ExpansionContractionPanel component. - * - * @param component the ExpansionContractionPanel component - */ - private void addComp(final Component component) { - deltaUnit.add(Box.createVerticalStrut(GuiCommon.BORDER_SIZE)); - deltaUnit.add(component); - deltaUnit.revalidate(); - } - - /** - * Reload the "Delta Data" and "SnapShot Data". - */ - private void reLoad() { - if (diffOffsets != null && diffOffsets.size() > 0) { - try { - draw(diffOffsets, false); - ssDlg.draw(diffOffsets.get(0), searchClass, filterList); - } catch (IOException e) { - GuiCommon.showMessage(this, GuiCommon.BASEE13, - JOptionPane.ERROR_MESSAGE); - } catch (ClassNotFoundException e) { - GuiCommon.showMessage(this, GuiCommon.BASEE13, - JOptionPane.ERROR_MESSAGE); - } - } - } - - /** - * Draw a chart ranking chart and heap usage. - * - * @param sortItem Sort key - */ - private void drawChart(final SnapShotHelper.SortItem sortItem) { - progressBar = new HeapProgressBar("Draw the statistics GC.", guimain); - progressBar.setVisible(true); - - if (sortItem == SnapShotHelper.SortItem.SIZE) { - rank.setTitle(GuiCommon.getResources().getString( - GuiCommon.TITLE_SIZE_DELTE)); - usage.setTitle(GuiCommon.getResources().getString( - GuiCommon.TITLE_SIZE_AREA)); - } else { - rank.setTitle(GuiCommon.getResources().getString( - GuiCommon.TITLE_INSTANCE_DELTE)); - usage.setTitle(GuiCommon.getResources().getString( - GuiCommon.TITLE_INSTANCE_AREA)); - } - - worker = new DiffWorker(sortItem, this); - worker.addPropertyChangeListener(this); - worker.execute(); - } - - /** - * Returns the Regular expression. - * - * @return Returns the Regular expression. - */ - public final List<Pattern> getFilterList() { - return filterList; - } - - /** - * Returns the Filter Results Class List. - * - * @return Returns the Filter Results Class List. - */ - public final Object[] getSearchClass() { - return searchClass; - } - - /** - * Starts drawing the SnapShot Data. - * - * @param offsetsList file position and SnapShotReader - * @param load load flag true:load, false:reload - * @throws IOException If an I/O error has occurred. - * @throws ClassNotFoundException Class of a serialized object cannot be - * found. - */ - public final void draw(final List<List<Object>> offsetsList, - final boolean load) throws IOException, ClassNotFoundException { - deltaUnit.setVisible(false); - deltaUnit.removeAll(); - nameList.clear(); - diffOffsets = offsetsList; - - if (load) { - searchText.clear(); - searchClass = null; - packageFilter.clear(); - filterEntriesModel.setRowCount(0); - } - - // JTable:Objects List - TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>( - diffEntriesModel); - sorter.setSortable(0, false); - diffEntries.setRowSorter(sorter); - diffEntries.getTableHeader().setReorderingAllowed(false); - - diffEntriesModel.setRowCount(0); - - SnapShot start = ((SnapShotReader) diffOffsets.get(0).get(1)) - .getSnapShot((Long) diffOffsets.get(0).get(0)); - SnapShot end = ((SnapShotReader) diffOffsets - .get(diffOffsets.size() - 1).get(1)) - .getSnapShot((Long) diffOffsets.get(diffOffsets.size() - 1) - .get(0)); - - Map<Long, ObjectData> diff = SnapShotHelper.calculateDiff( - start.getElements(), end.getElements()); - - Object[] ary = new Object[4]; - List<ObjectData> objectList = filterClassMap(diff); - - for (ObjectData obd : objectList) { - ary[0] = ""; - ary[1] = obd.getName(); - ary[2] = obd.getCount(); - ary[3] = obd.getTotalSize(); - diffEntriesModel.addRow(ary); - } - - JPanel objPanel = new JPanel(); - objPanel.setLayout(new BorderLayout()); - objPanel.setBackground(Color.WHITE); - - JPanel sortPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); - sortPanel.setBackground(Color.WHITE); - insBtn = new JButton(GuiCommon.getResources().getString( - GuiCommon.SORT_INSTANCE)); - sizeBtn = new JButton(GuiCommon.getResources().getString( - GuiCommon.SORT_SIZE)); - insBtn.setPreferredSize(new Dimension(130, 20)); - sizeBtn.setPreferredSize(new Dimension(100, 20)); - insBtn.addActionListener(guimain); - insBtn.setEnabled(true); - sizeBtn.addActionListener(guimain); - sizeBtn.setEnabled(false); - sortPanel.add(insBtn); - sortPanel.add(sizeBtn); - - JScrollPane diffScroll = new JScrollPane( - JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, - JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); - diffScroll.getViewport().setView(diffEntries); - - ArrayList<SortKey> sortKeys = new ArrayList<SortKey>(); - sortKeys.add(new SortKey(3, SortOrder.DESCENDING)); - diffEntries.getRowSorter().setSortKeys(sortKeys); - - objPanel.add(BorderLayout.NORTH, sortPanel); - objPanel.add(BorderLayout.CENTER, diffScroll); - objList.setComponent(objPanel, false); - - addComp(rank); - addComp(usage); - addComp(objList); - - drawChart(SnapShotHelper.SortItem.SIZE); - } - - /** - * Return the component. - * - * @return Return the Component - */ - public final JSplitPane getComp() { - return comp; - } - - /** - * Return the panel of Ranking chart. - * - * @return Return the panel of Ranking chart - */ - public final ChartPanel getRankChart() { - return rankChart; - } - - /** - * Return the panel of Usage chart. - * - * @return Return the panel of Usage chart - */ - public final ChartPanel getUsageChart() { - return usageChart; - } - - /** - * Return the offsets. - * - * @return Return the offsets - */ - public final Map<String, List<Object>> getOffsets() { - return offsets; - } - - /** - * Sets the dialog component. - * - * @param value the Main Component - */ - public final void setComp(final JSplitPane value) { - comp = value; - add(comp); - } - - /** - * Clear the delta data. - */ - public final void clear() { - deltaUnit.setVisible(false); - nameList.clear(); - if (diffOffsets != null) { - diffOffsets.clear(); - } - packageFilter.clear(); - filterList.clear(); - filterEntriesModel.setRowCount(0); - searchText.clear(); - searchClass = null; - selectBtn.setText(SELECT_BUTTON_NAME); - } - - /** - * Returns true if this task completed. Completion may be due to normal - * termination, an exception, or cancellation -- in all of these cases, this - * method will return true. - * - * @return true if this task completed - */ - public final boolean isDone() { - if (worker != null) { - return worker.isDone(); - } - return true; - } - - /** - * Invoked when an action occurs from GUIMain. - * - * @param arg0 ActionEvent - */ - public final void actionPerformed(final ActionEvent arg0) { - try { - if (arg0.getActionCommand().equals( - GuiCommon.getResources().getString( - GuiCommon.CLASS_FILTER_ADD))) { - - JFileChooser fileChoser = new JFileChooser(); - fileChoser.setCurrentDirectory(GuiCommon.getCurrentDir()); - fileChoser.setMultiSelectionEnabled(true); - fileChoser.setFileFilter(new FileNameExtensionFilter("XML", - "xml")); - fileChoser.setAcceptAllFileFilterUsed(false); - - if (fileChoser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { - try { - GuiCommon.setCurrentDir(fileChoser - .getCurrentDirectory()); - } catch (IOException e) { - GuiCommon.showMessage(this, GuiCommon.BASEE17, - JOptionPane.ERROR_MESSAGE); - } - PackageFilterReader reader = new PackageFilterReader( - fileChoser.getSelectedFile()); - - if (!packageFilter.add(reader.loadFilterFIle(this), - filterEntriesModel)) { - // Duplicate filter name - GuiCommon.showMessage(this, GuiCommon.BASEE10, - JOptionPane.ERROR_MESSAGE); - } - } - } else if (arg0.getSource().equals(addOkbtn)) { - createFilterList(); - if (filterEntriesModel.getRowCount() > 0) { - GuiCommon.showMessage(this, GuiCommon.BASEI01, - JOptionPane.INFORMATION_MESSAGE); - reLoad(); - } - } else if (arg0.getSource().equals(searchOkbtn)) { - // Class Search - Object[] tmpSelect = classList.getSelectedValues(); - if ((tmpSelect.length > 0) - || ((tmpSelect.length == 0) && (searchClass != null) && (searchClass.length > 0))) { - searchClass = tmpSelect; - GuiCommon.showMessage(this, GuiCommon.BASEI01, - JOptionPane.INFORMATION_MESSAGE); - reLoad(); - } - } else if (arg0.getSource().equals(searchClearbtn)) { - // Class Search Clear - searchText.setText(""); - selectBtn.setText(SELECT_BUTTON_NAME); - if (searchClass != null && searchClass.length > 0) { - searchClass = new Object[0]; - reLoad(); - } - } else if (arg0.getSource().equals(selectBtn)) { - // Select class list. - if (selectBtn.getText().equals(SELECT_BUTTON_NAME) - && (classList.getModel().getSize() > 0)) { - int[] indices = new int[classList.getModel().getSize()]; - for (int i = 0; i < indices.length; i++) { - indices[i] = i; - } - classList.setSelectedIndices(indices); - selectBtn.setText("Deselect All"); - } else { - classList.clearSelection(); - selectBtn.setText(SELECT_BUTTON_NAME); - } - } else if (arg0.getSource().equals(clearBtn)) { - // Class Filter Clear - filterEntriesModel.setRowCount(0); - packageFilter.clear(); - - if (filterList.size() > 0) { - filterList.clear(); - reLoad(); - } - } else if (arg0.getSource().equals(insBtn)) { - // Instances Rank & Delta graphs - drawChart(SnapShotHelper.SortItem.INSTANCE); - insBtn.setEnabled(false); - sizeBtn.setEnabled(true); - } else if (arg0.getSource().equals(sizeBtn)) { - // Size Rank & Delta graphs - drawChart(SnapShotHelper.SortItem.SIZE); - insBtn.setEnabled(true); - sizeBtn.setEnabled(false); - } - } catch (Throwable e) { - GuiCommon.showMessage(this, GuiCommon.BASEE13, - JOptionPane.ERROR_MESSAGE); - } - } - - @Override - public final void propertyChange(final PropertyChangeEvent evt) { - String strPropertyName = evt.getPropertyName(); - if ("progress".equals(strPropertyName)) { - int progress = (Integer) evt.getNewValue(); - progressBar.setValue(progress); - } - } - - /** - * extends {@link SwingWorker}<br> - * <br> - * SwingWorker thread drawing done in the time-consuming process chart. - */ - class DiffWorker extends SwingWorker<Object, Object> { - - /** Sort key object list. */ - private SnapShotHelper.SortItem sortItem; - - /** the owner DiffDialog. */ - private DiffDialog diffDialog; - - /** - * Create a SwingWorker. - * - * @param sort sort item - * @param parent the owner Dialog - */ - public DiffWorker(final SnapShotHelper.SortItem sort, - final DiffDialog parent) { - sortItem = sort; - diffDialog = parent; - } - - @Override - protected Object doInBackground() throws Exception { - drawRankingChart(); - drawUsageChart(); - return null; - } - - @Override - protected void done() { - super.done(); - progressBar.setVisible(false); - usage.validate(); - - deltaUnit.setVisible(true); - diffDialog.validate(); - diffDialog.getOwner().setCursor(Cursor.getDefaultCursor()); - } - - /** - * Draw a chart ranking the difference between snapshots. - * - * @throws IOException If an I/O error has occurred. - * @throws ClassNotFoundException Class of a serialized object cannot be - * found. - */ - private void drawRankingChart() throws IOException, - ClassNotFoundException { - SnapShot before; - SnapShot after; - Map<Long, ObjectData> diff; - ObjectData[] tmpList; - StringBuilder labelStr = new StringBuilder(); - - DefaultCategoryDataset rankDataSet = new DefaultCategoryDataset(); - - SimpleDateFormat sdf = new SimpleDateFormat( - GuiCommon.CHART_DATE_FORMAT); - - List<String> hideLabel = new ArrayList<String>(); - int k = diffOffsets.size() / 10; - int size = diffOffsets.size(); - for (int i = 0; i < diffOffsets.size() - 1; i++) { - List<Object> beforeList = diffOffsets.get(i); - List<Object> afterList = diffOffsets.get(i + 1); - - before = ((SnapShotReader) beforeList.get(1)) - .getSnapShot((Long) beforeList.get(0)); - after = ((SnapShotReader) afterList.get(1)) - .getSnapShot((Long) afterList.get(0)); - - // x-axis labels - labelStr.delete(0, labelStr.length()); - labelStr.append(sdf - .format(before.getHeader().getSnapShotDate())); - - diff = SnapShotHelper.calculateDiff(before.getElements(), - after.getElements()); - tmpList = SnapShotHelper.getSortedArray(diff, sortItem, - SnapShotHelper.SortOrder.DESC); - - List<ObjectData> result = startFilter(tmpList); - - int j = 1; - for (ObjectData objectdata : result) { - rankDataSet.addValue(j, new MapKey(objectdata), - labelStr.toString()); - if (j++ == GuiCommon.getRankLevel()) { - break; - } - } - - if (k > 0 && (i % k != 0) - && !hideLabel.contains(labelStr.toString())) { - hideLabel.add(labelStr.toString()); - } - setProgress(50 * i / size); - } - - JFreeChart chart = ChartFactory.createLineChart("", "", "Rank", - rankDataSet, PlotOrientation.VERTICAL, false, true, false); - chart.setBackgroundPaint(Color.WHITE); - - CategoryPlot plot = (CategoryPlot) chart.getPlot(); - plot.setBackgroundPaint(new Color(GuiCommon.getBgColor())); - ((LineAndShapeRenderer) plot.getRenderer()) - .setBaseShapesVisible(true); - ValueAxis axis = plot.getRangeAxis(); - axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - axis.setInverted(true); - axis.setAutoRange(false); - axis.setRange(0.8, GuiCommon.getRankLevel() + 0.2); - GraphColorHelper.adjustColor(rankDataSet, plot); - - hideCategoryLabel(plot.getDomainAxis(), hideLabel); - - rankChart = new ChartPanel(chart); - - rank.setComponent(rankChart, false); - rankChart.addChartMouseListener(guimain); - } - - /** - * Draw a stacked heap usage. - * - * @throws IOException If an I/O error has occurred. - * @throws ClassNotFoundException Class of a serialized object cannot be - * found. - */ - private void drawUsageChart() throws IOException, - ClassNotFoundException { - SnapShot snapShot; - long heapUsage; - ObjectData[] result; - StringBuilder labelStr = new StringBuilder(); - DefaultCategoryDataset stackDataSet = new DefaultCategoryDataset(); - - SimpleDateFormat sdf = new SimpleDateFormat( - GuiCommon.CHART_DATE_FORMAT); - - offsets = new HashMap<String, List<Object>>(); - - List<String> hideLabel = new ArrayList<String>(); - int size = diffOffsets.size(); - int k = size / 10; - - // SnapShot - int per = 0; - int rmv = 0; - for (List<Object> data : diffOffsets) { - snapShot = ((SnapShotReader) data.get(1)) - .getSnapShot((Long) data.get(0)); - heapUsage = snapShot.getHeapUsage(); - - String before = labelStr.toString(); - labelStr.delete(0, labelStr.length()); - labelStr.append(sdf.format(snapShot.getHeader() - .getSnapShotDate())); - - result = SnapShotHelper.getSortedArray(snapShot.getElements(), - sortItem, SnapShotHelper.SortOrder.DESC); - - List<ObjectData> viewList = startFilter(result); - - // SnapShot Data - offsets.put(sdf.format(snapShot.getHeader().getSnapShotDate()), - data); - - // Object - int j = 0; - for (ObjectData objectdata : viewList) { - if (j++ < GuiCommon.getRankLevel()) { - stackDataSet.addValue( - (double) objectdata.getTotalSize() - / GuiCommon.BINARY_PREFIX, new MapKey( - objectdata), labelStr.toString()); - heapUsage -= objectdata.getTotalSize(); - } - nameList.add(objectdata.getName()); - } - - if ((searchClass == null || searchClass.length == 0) - && (filterList == null || filterList.size() == 0)) { - stackDataSet.addValue((double) heapUsage - / GuiCommon.BINARY_PREFIX, new MapKey(0, "Others"), - labelStr.toString()); - } - - if (!before.equals(labelStr.toString()) && (k > 0) - && (rmv++ % k != 0)) { - hideLabel.add(labelStr.toString()); - } - // Sets the progress bound property. - setProgress(50 + 50 * (++per) / size); - } - - searchText.addList(nameList); - - JFreeChart chart = ChartFactory.createStackedAreaChart("", "", - "Usage(KB)", stackDataSet, PlotOrientation.VERTICAL, false, - true, true); - chart.setBackgroundPaint(Color.WHITE); - - CategoryPlot plot = chart.getCategoryPlot(); - plot.setBackgroundPaint(new Color(GuiCommon.getBgColor())); - hideCategoryLabel(plot.getDomainAxis(), hideLabel); - - GraphColorHelper.adjustColor(stackDataSet, chart.getPlot()); - usageChart = new ChartPanel(chart); - - usage.setComponent(usageChart, true); - - usageChart.addChartMouseListener(guimain); - } - - /** - * Hide unwanted items out of the X axis label. - * - * @param ca CategoryAxis - * @param hideLabel Hide item list - */ - private void hideCategoryLabel(final CategoryAxis ca, - final List<String> hideLabel) { - ca.setAxisLineVisible(false); - ca.setCategoryLabelPositions(CategoryLabelPositions - .createUpRotationLabelPositions(Math.PI / ANGLE)); - - for (String label : hideLabel) { - ca.setTickLabelPaint(label, new Color(0, 0, 0, 0)); - } - } - } -} +/* + * DiffDialog.java + * Created on 2011/10/13 + * + * Copyright (C) 2011-2013 Nippon Telegraph and Telephone Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +package jp.co.ntt.oss.heapstats.gui; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Paint; +import java.awt.event.ActionEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.DefaultListModel; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFileChooser; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; +import javax.swing.JTable; +import javax.swing.RowSorter.SortKey; +import javax.swing.SortOrder; +import javax.swing.SwingWorker; +import javax.swing.filechooser.FileNameExtensionFilter; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumnModel; +import javax.swing.table.TableModel; +import javax.swing.table.TableRowSorter; + +import jp.co.ntt.oss.heapstats.container.MapKey; +import jp.co.ntt.oss.heapstats.container.ObjectData; +import jp.co.ntt.oss.heapstats.container.PackageFilter; +import jp.co.ntt.oss.heapstats.container.SnapShot; +import jp.co.ntt.oss.heapstats.gui.graph.GraphColorHelper; +import jp.co.ntt.oss.heapstats.gui.snapshot.PackageFilterReader; +import jp.co.ntt.oss.heapstats.gui.snapshot.SnapShotHelper; +import jp.co.ntt.oss.heapstats.gui.snapshot.SnapShotReader; + +import org.jfree.chart.ChartFactory; +import org.jfree.chart.ChartPanel; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.axis.CategoryAxis; +import org.jfree.chart.axis.CategoryLabelPositions; +import org.jfree.chart.axis.NumberAxis; +import org.jfree.chart.axis.ValueAxis; +import org.jfree.chart.plot.CategoryPlot; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.renderer.category.LineAndShapeRenderer; +import org.jfree.data.category.DefaultCategoryDataset; + +/** + * extends {@link JDialog}<br> + * implements {@link PropertyChangeListener}<br> + * <br> + * Delta Index chart, draw a stacked heap usage chart. In addition, articles can + * be done by filter class. + */ +public class DiffDialog extends JDialog implements + PropertyChangeListener { + /** serialVersionUID. */ + private static final long serialVersionUID = 31766154511197856L; + + /** Angle of the axis labels. */ + private static final double ANGLE = 6.0; + + /** The button name for choosing all the classes for search. */ + private static final String SELECT_BUTTON_NAME = " Select All "; + + /** A SnapShot Dialog. */ + private SnapShotDialog ssDlg; + + /** Mainframe heapstats. */ + private GUIMain guimain; + + /** Main Component. */ + private JSplitPane comp; + + /** Delta data information display unit. */ + private Box deltaUnit = Box.createVerticalBox(); + + /** Ranking Chart Panel. */ + private ExpansionContractionPanel rank; + + /** Heap Usage Chart Panel. */ + private ExpansionContractionPanel usage; + + /** Objects List. */ + private ExpansionContractionPanel objList; + + /** Objects List DefaultTableModel. */ + private DiffEntriesModel diffEntriesModel; + + /** Objects List Table. */ + private JTable diffEntries; + + /** Class Filter TableModel. */ + private FilterEntriesModel filterEntriesModel; + + /** Class Filter Table. */ + private JTable filterEntries; + + /** Class Filter OK Button. */ + private JButton addOkbtn; + + /** Class Filter Clean Button. */ + private JButton clearBtn; + + /** Class Filter Information. */ + private PackageFilter packageFilter; + + /** Regular expression. */ + private List<Pattern> filterList; + + /** Filter Results Class List. */ + private Object[] searchClass; + + /** Class Search List. */ + private JList classList; + + /** Class Search. */ + private SearchJTextField searchText; + + /** Class Search OK Button. */ + private JButton searchOkbtn; + + /** Class Search Clear Button. */ + private JButton searchClearbtn; + + /** Select button. */ + private JButton selectBtn; + + /** Sort Button. instance */ + private JButton insBtn; + + /** Sort Button. heap size */ + private JButton sizeBtn; + + /** A class list search paths. */ + private Set<String> nameList; + + /** Offsets Key is Date. Data is file position and SnapShotReader. */ + private Map<String, List<Object>> offsets; + + /** the List is file position and SnapShotReader. */ + private List<List<Object>> diffOffsets; + + /** ProgressBar. */ + private HeapProgressBar progressBar; + + /** The SwingWorker for drawing graphs. */ + private DiffWorker worker; + + /** The panel of Ranking Chart. */ + private ChartPanel rankChart; + + /** The panel of Usage Chart. */ + private ChartPanel usageChart; + + /** + * Creates a modeless dialog with the specified Dialog as its owner. + * + * @param owner the owner Dialog from which the dialog is displayed or null + * if this dialog has no owner + * @param dialog the snapshot dialog + */ + public DiffDialog(final GUIMain owner, final SnapShotDialog dialog) { + super(owner); + + guimain = owner; + ssDlg = dialog; + rank = null; + usage = null; + objList = null; + comp = null; + searchClass = null; + filterList = new ArrayList<Pattern>(); + packageFilter = new PackageFilter(); + nameList = new HashSet<String>(); + + setTitle(GuiCommon.getResources().getString(GuiCommon.TAB_TITLE_DELA)); + setSize(GuiCommon.DEFAULT_DIALOG_WIDTH, GuiCommon.DEFAULT_DIALOG_HEIGHT); + setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); + setModal(false); + + addComponent(); + setLocationByPlatform(true); + } + + /** + * Create components to draw on the screen. + */ + private void addComponent() { + Box search = Box.createVerticalBox(); + search.setBorder(BorderFactory.createEmptyBorder(GuiCommon.BORDER_SIZE, + GuiCommon.BORDER_SIZE, GuiCommon.BORDER_SIZE, + GuiCommon.BORDER_SIZE)); + + JPanel diffPanel = new JPanel(); + diffPanel.setLayout(new BorderLayout()); + deltaUnit.setBorder(BorderFactory.createEmptyBorder( + GuiCommon.BORDER_SIZE, GuiCommon.BORDER_SIZE, + GuiCommon.BORDER_SIZE, GuiCommon.BORDER_SIZE)); + + comp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, search, diffPanel); + comp.setOneTouchExpandable(true); + + search.add(Box.createVerticalStrut(GuiCommon.BORDER_SIZE)); + search.add(addFilterComponent()); + search.add(Box.createVerticalStrut(GuiCommon.BORDER_SIZE)); + search.add(addIncrementComponent()); + + diffPanel.add(deltaUnit); + + diffEntriesModel = new DiffEntriesModel(); + diffEntries = new JTable(diffEntriesModel) { + /** serialVersionUID. */ + private static final long serialVersionUID = -925317579655004381L; + + @Override + public Component prepareRenderer(final TableCellRenderer tcr, + final int row, final int column) { + Component retVal = super.prepareRenderer(tcr, row, column); + + retVal.setForeground(getForeground()); + Paint bgPaint = GraphColorHelper.getColor((String) getValueAt( + row, 1)); + if (bgPaint != null && column == 0) { + retVal.setBackground((Color) bgPaint); + } else { + retVal.setBackground(Color.WHITE); + } + return retVal; + } + }; + + TableColumnModel model = diffEntries.getColumnModel(); + model.getColumn(0).setPreferredWidth(GuiCommon.COL_SIZE_COLOR); + model.getColumn(1).setPreferredWidth(GuiCommon.COL_SIZE_CLASSNAME); + + rank = new ExpansionContractionPanel(GuiCommon.getResources() + .getString(GuiCommon.TITLE_SIZE_DELTE)); + usage = new ExpansionContractionPanel(GuiCommon.getResources() + .getString(GuiCommon.TITLE_SIZE_AREA)); + objList = new ExpansionContractionPanel(GuiCommon.getResources() + .getString(GuiCommon.TITLE_OBJECTLIST)); + } + + /** + * Creates a Class filter component. + * + * @return Return the Filter ExpansionContractionPanel + */ + private JPanel addFilterComponent() { + // Class Filter + ExpansionContractionPanel filterMain = new ExpansionContractionPanel( + GuiCommon.getResources().getString( + GuiCommon.CLASS_FILTER_LABEL_TITLE)); + JPanel classPanel = new JPanel(new BorderLayout()); + filterMain.setComponent(classPanel, true); + classPanel.setBackground(Color.WHITE); + + JPanel addPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); + addPanel.setBackground(Color.WHITE); + + JButton addFilter = new JButton(GuiCommon.getResources().getString( + GuiCommon.CLASS_FILTER_ADD)); + addFilter.setPreferredSize(new Dimension(120, 20)); + addFilter.addActionListener(guimain); + + addPanel.add(addFilter); + + filterEntriesModel = new FilterEntriesModel(); + filterEntries = new JTable(filterEntriesModel); + + JScrollPane pkgScroll = new JScrollPane(); + pkgScroll.getViewport().setView(filterEntries); + + JPanel okPanel = new JPanel(); + okPanel.setLayout(new BoxLayout(okPanel, BoxLayout.X_AXIS)); + okPanel.setBackground(Color.WHITE); + okPanel.add(Box.createVerticalStrut(GuiCommon.BORDER_SIZE)); + + clearBtn = new JButton("Clear"); + clearBtn.setMaximumSize(new Dimension(70, 20)); + clearBtn.addActionListener(guimain); + okPanel.add(clearBtn); + okPanel.add(new JLabel(" ")); + + addOkbtn = new JButton("OK"); + addOkbtn.setMaximumSize(new Dimension(60, 20)); + addOkbtn.addActionListener(guimain); + + okPanel.add(addOkbtn); + + TableColumnModel model = filterEntries.getColumnModel(); + model.getColumn(0).setMaxWidth(50); + + classPanel.add(BorderLayout.NORTH, addPanel); + classPanel.add(BorderLayout.CENTER, pkgScroll); + classPanel.add(BorderLayout.SOUTH, okPanel); + + return filterMain; + } + + /** + * Creates a Class search component. + * + * @return Return the Incremental Search Component + */ + private JPanel addIncrementComponent() { + // Incremental Search + ExpansionContractionPanel searchMain = new ExpansionContractionPanel( + GuiCommon.getResources().getString( + GuiCommon.CLASS_SEARCH_LABEL_TITLE)); + JPanel increPanel = new JPanel(new BorderLayout()); + increPanel.setBackground(Color.WHITE); + + searchMain.setComponent(increPanel, true); + JPanel okPanel = new JPanel(); + okPanel.setLayout(new BoxLayout(okPanel, BoxLayout.X_AXIS)); + okPanel.setBackground(Color.WHITE); + + searchClearbtn = new JButton("Clear"); + searchClearbtn.setMaximumSize(new Dimension(70, 20)); + searchClearbtn.addActionListener(guimain); + searchOkbtn = new JButton("OK"); + searchOkbtn.setMaximumSize(new Dimension(60, 20)); + searchOkbtn.addActionListener(guimain); + selectBtn = new JButton(SELECT_BUTTON_NAME); + selectBtn.setMinimumSize(new Dimension(110, 20)); + selectBtn.setMaximumSize(new Dimension(110, 20)); + selectBtn.addActionListener(guimain); + + okPanel.add(selectBtn); + okPanel.add(Box.createVerticalStrut(GuiCommon.BORDER_SIZE)); + okPanel.add(new JLabel(" ")); + okPanel.add(searchClearbtn); + okPanel.add(new JLabel(" ")); + okPanel.add(searchOkbtn); + + DefaultListModel classModel = new DefaultListModel(); + classList = new JList(classModel); + classList.setVisibleRowCount(50); + JScrollPane listScroll = new JScrollPane(); + listScroll.getViewport().setView(classList); + + searchText = new SearchJTextField(0, classModel); + + // add(p1); + increPanel.add(BorderLayout.NORTH, searchText); + increPanel.add(BorderLayout.CENTER, listScroll); + increPanel.add(BorderLayout.SOUTH, okPanel); + + return searchMain; + } + + /** + * Create an exclusion list for the class. + */ + private void createFilterList() { + // Class Filter + filterList.clear(); + for (int i = 0; i < filterEntriesModel.getRowCount(); i++) { + if ((Boolean) filterEntriesModel.getValueAt(i, 0)) { + List<String> datas = packageFilter + .get((String) filterEntriesModel.getValueAt(i, 1)); + for (int j = 1; j < datas.size(); j++) { + StringBuilder buf = new StringBuilder(); + buf.append("(^\\W*|L|\\W*L)?"); + if (GuiCommon.getClassRename()) { + buf.append(datas.get(j).replace("\\", ".")); + } else { + buf.append(datas.get(j)); + if ((datas.get(j).lastIndexOf(";") == -1) + && (datas.get(j).lastIndexOf("*") == -1)) { + buf.append("(;)?"); + } + } + filterList.add(Pattern.compile(buf.toString(), + Pattern.CASE_INSENSITIVE)); + } + } + } + } + + /** + * Filter class to return a list of articles ObjectData made. + * + * @param diff Class Map to be filtered + * @return Return the class filtered list + */ + private List<ObjectData> filterClassMap(final Map<Long, ObjectData> diff) { + ObjectData[] list = new ObjectData[diff.size()]; + + // Start Filter + int i = 0; + for (Map.Entry<Long, ObjectData> elmt : diff.entrySet()) { + list[i++] = elmt.getValue(); + } + + return startFilter(list); + } + + /** + * Filter class to return a list of articles ObjectData made. + * + * @param list ObjectData + * @return Return the ObjectData filtered list + */ + private List<ObjectData> startFilter(final ObjectData[] list) { + List<ObjectData> tmpList = new ArrayList<ObjectData>(); + List<ObjectData> viewSet = new ArrayList<ObjectData>(); + + // Start Filter + for (ObjectData elmt : list) { + boolean match = false; + for (Pattern ptn : filterList) { + Matcher matcher = ptn.matcher(elmt.getName()); + if (matcher.matches()) { + match = true; + break; + } + } + + if (!match) { + // Matches or, when there is no filter + tmpList.add(elmt); + } + } + + // Class Search + if (searchClass != null && searchClass.length > 0) { + for (ObjectData data : tmpList) { + for (Object path : searchClass) { + if (data.getName().equals(path)) { + viewSet.add(data); + } + } + } + } else { + // when there is no filter + viewSet.addAll(tmpList); + } + return viewSet; + } + + /** + * Add a ExpansionContractionPanel component. + * + * @param component the ExpansionContractionPanel component + */ + private void addComp(final Component component) { + deltaUnit.add(Box.createVerticalStrut(GuiCommon.BORDER_SIZE)); + deltaUnit.add(component); + deltaUnit.revalidate(); + } + + /** + * Reload the "Delta Data" and "SnapShot Data". + */ + private void reLoad() { + if (diffOffsets != null && diffOffsets.size() > 0) { + try { + draw(diffOffsets, false); + ssDlg.draw(diffOffsets.get(0), searchClass, filterList); + } catch (IOException e) { + GuiCommon.showMessage(this, GuiCommon.BASEE13, + JOptionPane.ERROR_MESSAGE); + } catch (ClassNotFoundException e) { + GuiCommon.showMessage(this, GuiCommon.BASEE13, + JOptionPane.ERROR_MESSAGE); + } + } + } + + /** + * Draw a chart ranking chart and heap usage. + * + * @param sortItem Sort key + */ + private void drawChart(final SnapShotHelper.SortItem sortItem) { + progressBar = new HeapProgressBar("Draw the statistics GC.", guimain); + progressBar.setVisible(true); + + if (sortItem == SnapShotHelper.SortItem.SIZE) { + rank.setTitle(GuiCommon.getResources().getString( + GuiCommon.TITLE_SIZE_DELTE)); + usage.setTitle(GuiCommon.getResources().getString( + GuiCommon.TITLE_SIZE_AREA)); + } else { + rank.setTitle(GuiCommon.getResources().getString( + GuiCommon.TITLE_INSTANCE_DELTE)); + usage.setTitle(GuiCommon.getResources().getString( + GuiCommon.TITLE_INSTANCE_AREA)); + } + + worker = new DiffWorker(sortItem, this); + worker.addPropertyChangeListener(this); + worker.execute(); + } + + /** + * Returns the Regular expression. + * + * @return Returns the Regular expression. + */ + public final List<Pattern> getFilterList() { + return filterList; + } + + /** + * Returns the Filter Results Class List. + * + * @return Returns the Filter Results Class List. + */ + public final Object[] getSearchClass() { + return searchClass; + } + + /** + * Starts drawing the SnapShot Data. + * + * @param offsetsList file position and SnapShotReader + * @param load load flag true:load, false:reload + * @throws IOException If an I/O error has occurred. + * @throws ClassNotFoundException Class of a serialized object cannot be + * found. + */ + public final void draw(final List<List<Object>> offsetsList, + final boolean load) throws IOException, ClassNotFoundException { + deltaUnit.setVisible(false); + deltaUnit.removeAll(); + nameList.clear(); + diffOffsets = offsetsList; + + if (load) { + searchText.clear(); + searchClass = null; + packageFilter.clear(); + filterEntriesModel.setRowCount(0); + } + + // JTable:Objects List + TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>( + diffEntriesModel); + sorter.setSortable(0, false); + diffEntries.setRowSorter(sorter); + diffEntries.getTableHeader().setReorderingAllowed(false); + + diffEntriesModel.setRowCount(0); + + SnapShot start = ((SnapShotReader) diffOffsets.get(0).get(1)) + .getSnapShot((Long) diffOffsets.get(0).get(0)); + SnapShot end = ((SnapShotReader) diffOffsets + .get(diffOffsets.size() - 1).get(1)) + .getSnapShot((Long) diffOffsets.get(diffOffsets.size() - 1) + .get(0)); + + Map<Long, ObjectData> diff = SnapShotHelper.calculateDiff( + start.getElements(), end.getElements()); + + Object[] ary = new Object[4]; + List<ObjectData> objectList = filterClassMap(diff); + + for (ObjectData obd : objectList) { + ary[0] = ""; + ary[1] = obd.getName(); + ary[2] = obd.getCount(); + ary[3] = obd.getTotalSize(); + diffEntriesModel.addRow(ary); + } + + JPanel objPanel = new JPanel(); + objPanel.setLayout(new BorderLayout()); + objPanel.setBackground(Color.WHITE); + + JPanel sortPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); + sortPanel.setBackground(Color.WHITE); + insBtn = new JButton(GuiCommon.getResources().getString( + GuiCommon.SORT_INSTANCE)); + sizeBtn = new JButton(GuiCommon.getResources().getString( + GuiCommon.SORT_SIZE)); + insBtn.setPreferredSize(new Dimension(130, 20)); + sizeBtn.setPreferredSize(new Dimension(100, 20)); + insBtn.addActionListener(guimain); + insBtn.setEnabled(true); + sizeBtn.addActionListener(guimain); + sizeBtn.setEnabled(false); + sortPanel.add(insBtn); + sortPanel.add(sizeBtn); + + JScrollPane diffScroll = new JScrollPane( + JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, + JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + diffScroll.getViewport().setView(diffEntries); + + ArrayList<SortKey> sortKeys = new ArrayList<SortKey>(); + sortKeys.add(new SortKey(3, SortOrder.DESCENDING)); + diffEntries.getRowSorter().setSortKeys(sortKeys); + + objPanel.add(BorderLayout.NORTH, sortPanel); + objPanel.add(BorderLayout.CENTER, diffScroll); + objList.setComponent(objPanel, false); + + addComp(rank); + addComp(usage); + addComp(objList); + + drawChart(SnapShotHelper.SortItem.SIZE); + } + + /** + * Return the component. + * + * @return Return the Component + */ + public final JSplitPane getComp() { + return comp; + } + + /** + * Return the panel of Ranking chart. + * + * @return Return the panel of Ranking chart + */ + public final ChartPanel getRankChart() { + return rankChart; + } + + /** + * Return the panel of Usage chart. + * + * @return Return the panel of Usage chart + */ + public final ChartPanel getUsageChart() { + return usageChart; + } + + /** + * Return the offsets. + * + * @return Return the offsets + */ + public final Map<String, List<Object>> getOffsets() { + return offsets; + } + + /** + * Sets the dialog component. + * + * @param value the Main Component + */ + public final void setComp(final JSplitPane value) { + comp = value; + add(comp); + } + + /** + * Clear the delta data. + */ + public final void clear() { + deltaUnit.setVisible(false); + nameList.clear(); + if (diffOffsets != null) { + diffOffsets.clear(); + } + packageFilter.clear(); + filterList.clear(); + filterEntriesModel.setRowCount(0); + searchText.clear(); + searchClass = null; + selectBtn.setText(SELECT_BUTTON_NAME); + } + + /** + * Returns true if this task completed. Completion may be due to normal + * termination, an exception, or cancellation -- in all of these cases, this + * method will return true. + * + * @return true if this task completed + */ + public final boolean isDone() { + if (worker != null) { + return worker.isDone(); + } + return true; + } + + /** + * Invoked when an action occurs from GUIMain. + * + * @param arg0 ActionEvent + */ + public final void actionPerformed(final ActionEvent arg0) { + try { + if (arg0.getActionCommand().equals( + GuiCommon.getResources().getString( + GuiCommon.CLASS_FILTER_ADD))) { + + JFileChooser fileChoser = new JFileChooser(); + fileChoser.setCurrentDirectory(GuiCommon.getCurrentDir()); + fileChoser.setMultiSelectionEnabled(true); + fileChoser.setFileFilter(new FileNameExtensionFilter("XML", + "xml")); + fileChoser.setAcceptAllFileFilterUsed(false); + + if (fileChoser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { + try { + GuiCommon.setCurrentDir(fileChoser + .getCurrentDirectory()); + } catch (IOException e) { + GuiCommon.showMessage(this, GuiCommon.BASEE17, + JOptionPane.ERROR_MESSAGE); + } + PackageFilterReader reader = new PackageFilterReader( + fileChoser.getSelectedFile()); + + if (!packageFilter.add(reader.loadFilterFIle(this), + filterEntriesModel)) { + // Duplicate filter name + GuiCommon.showMessage(this, GuiCommon.BASEE10, + JOptionPane.ERROR_MESSAGE); + } + } + } else if (arg0.getSource().equals(addOkbtn)) { + createFilterList(); + if (filterEntriesModel.getRowCount() > 0) { + GuiCommon.showMessage(this, GuiCommon.BASEI01, + JOptionPane.INFORMATION_MESSAGE); + reLoad(); + } + } else if (arg0.getSource().equals(searchOkbtn)) { + // Class Search + Object[] tmpSelect = classList.getSelectedValues(); + if ((tmpSelect.length > 0) + || ((tmpSelect.length == 0) && (searchClass != null) && (searchClass.length > 0))) { + searchClass = tmpSelect; + GuiCommon.showMessage(this, GuiCommon.BASEI01, + JOptionPane.INFORMATION_MESSAGE); + reLoad(); + } + } else if (arg0.getSource().equals(searchClearbtn)) { + // Class Search Clear + searchText.setText(""); + selectBtn.setText(SELECT_BUTTON_NAME); + if (searchClass != null && searchClass.length > 0) { + searchClass = new Object[0]; + reLoad(); + } + } else if (arg0.getSource().equals(selectBtn)) { + // Select class list. + if (selectBtn.getText().equals(SELECT_BUTTON_NAME) + && (classList.getModel().getSize() > 0)) { + int[] indices = new int[classList.getModel().getSize()]; + for (int i = 0; i < indices.length; i++) { + indices[i] = i; + } + classList.setSelectedIndices(indices); + selectBtn.setText("Deselect All"); + } else { + classList.clearSelection(); + selectBtn.setText(SELECT_BUTTON_NAME); + } + } else if (arg0.getSource().equals(clearBtn)) { + // Class Filter Clear + filterEntriesModel.setRowCount(0); + packageFilter.clear(); + + if (filterList.size() > 0) { + filterList.clear(); + reLoad(); + } + } else if (arg0.getSource().equals(insBtn)) { + // Instances Rank & Delta graphs + drawChart(SnapShotHelper.SortItem.INSTANCE); + insBtn.setEnabled(false); + sizeBtn.setEnabled(true); + } else if (arg0.getSource().equals(sizeBtn)) { + // Size Rank & Delta graphs + drawChart(SnapShotHelper.SortItem.SIZE); + insBtn.setEnabled(true); + sizeBtn.setEnabled(false); + } + } catch (Throwable e) { + GuiCommon.showMessage(this, GuiCommon.BASEE13, + JOptionPane.ERROR_MESSAGE); + } + } + + @Override + public final void propertyChange(final PropertyChangeEvent evt) { + String strPropertyName = evt.getPropertyName(); + if ("progress".equals(strPropertyName)) { + int progress = (Integer) evt.getNewValue(); + progressBar.setValue(progress); + } + } + + /** + * extends {@link SwingWorker}<br> + * <br> + * SwingWorker thread drawing done in the time-consuming process chart. + */ + class DiffWorker extends SwingWorker<Object, Object> { + + /** Sort key object list. */ + private SnapShotHelper.SortItem sortItem; + + /** the owner DiffDialog. */ + private DiffDialog diffDialog; + + /** + * Create a SwingWorker. + * + * @param sort sort item + * @param parent the owner Dialog + */ + public DiffWorker(final SnapShotHelper.SortItem sort, + final DiffDialog parent) { + sortItem = sort; + diffDialog = parent; + } + + @Override + protected Object doInBackground() throws Exception { + drawRankingChart(); + drawUsageChart(); + return null; + } + + @Override + protected void done() { + super.done(); + progressBar.setVisible(false); + usage.validate(); + + deltaUnit.setVisible(true); + diffDialog.validate(); + diffDialog.getOwner().setCursor(Cursor.getDefaultCursor()); + } + + /** + * Draw a chart ranking the difference between snapshots. + * + * @throws IOException If an I/O error has occurred. + * @throws ClassNotFoundException Class of a serialized object cannot be + * found. + */ + private void drawRankingChart() throws IOException, + ClassNotFoundException { + SnapShot before; + SnapShot after; + Map<Long, ObjectData> diff; + ObjectData[] tmpList; + StringBuilder labelStr = new StringBuilder(); + + DefaultCategoryDataset rankDataSet = new DefaultCategoryDataset(); + + SimpleDateFormat sdf = new SimpleDateFormat( + GuiCommon.CHART_DATE_FORMAT); + + List<String> hideLabel = new ArrayList<String>(); + int k = diffOffsets.size() / 10; + int size = diffOffsets.size(); + for (int i = 0; i < diffOffsets.size() - 1; i++) { + List<Object> beforeList = diffOffsets.get(i); + List<Object> afterList = diffOffsets.get(i + 1); + + before = ((SnapShotReader) beforeList.get(1)) + .getSnapShot((Long) beforeList.get(0)); + after = ((SnapShotReader) afterList.get(1)) + .getSnapShot((Long) afterList.get(0)); + + // x-axis labels + labelStr.delete(0, labelStr.length()); + labelStr.append(sdf + .format(before.getHeader().getSnapShotDate())); + + diff = SnapShotHelper.calculateDiff(before.getElements(), + after.getElements()); + tmpList = SnapShotHelper.getSortedArray(diff, sortItem, + SnapShotHelper.SortOrder.DESC); + + List<ObjectData> result = startFilter(tmpList); + + int j = 1; + for (ObjectData objectdata : result) { + rankDataSet.addValue(j, new MapKey(objectdata), + labelStr.toString()); + if (j++ == GuiCommon.getRankLevel()) { + break; + } + } + + if (k > 0 && (i % k != 0) + && !hideLabel.contains(labelStr.toString())) { + hideLabel.add(labelStr.toString()); + } + setProgress(50 * i / size); + } + + JFreeChart chart = ChartFactory.createLineChart("", "", "Rank", + rankDataSet, PlotOrientation.VERTICAL, false, true, false); + chart.setBackgroundPaint(Color.WHITE); + + CategoryPlot plot = (CategoryPlot) chart.getPlot(); + plot.setBackgroundPaint(new Color(GuiCommon.getBgColor())); + ((LineAndShapeRenderer) plot.getRenderer()) + .setBaseShapesVisible(true); + ValueAxis axis = plot.getRangeAxis(); + axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); + axis.setInverted(true); + axis.setAutoRange(false); + axis.setRange(0.8, GuiCommon.getRankLevel() + 0.2); + GraphColorHelper.adjustColor(rankDataSet, plot); + + hideCategoryLabel(plot.getDomainAxis(), hideLabel); + + rankChart = new ChartPanel(chart); + + rank.setComponent(rankChart, false); + rankChart.addChartMouseListener(guimain); + } + + /** + * Draw a stacked heap usage. + * + * @throws IOException If an I/O error has occurred. + * @throws ClassNotFoundException Class of a serialized object cannot be + * found. + */ + private void drawUsageChart() throws IOException, + ClassNotFoundException { + SnapShot snapShot; + long heapUsage; + ObjectData[] result; + StringBuilder labelStr = new StringBuilder(); + DefaultCategoryDataset stackDataSet = new DefaultCategoryDataset(); + + SimpleDateFormat sdf = new SimpleDateFormat( + GuiCommon.CHART_DATE_FORMAT); + + offsets = new HashMap<String, List<Object>>(); + + List<String> hideLabel = new ArrayList<String>(); + int size = diffOffsets.size(); + int k = size / 10; + + // SnapShot + int per = 0; + int rmv = 0; + for (List<Object> data : diffOffsets) { + snapShot = ((SnapShotReader) data.get(1)) + .getSnapShot((Long) data.get(0)); + heapUsage = snapShot.getHeapUsage(); + + String before = labelStr.toString(); + labelStr.delete(0, labelStr.length()); + labelStr.append(sdf.format(snapShot.getHeader() + .getSnapShotDate())); + + result = SnapShotHelper.getSortedArray(snapShot.getElements(), + sortItem, SnapShotHelper.SortOrder.DESC); + + List<ObjectData> viewList = startFilter(result); + + // SnapShot Data + offsets.put(sdf.format(snapShot.getHeader().getSnapShotDate()), + data); + + // Object + int j = 0; + for (ObjectData objectdata : viewList) { + if (j++ < GuiCommon.getRankLevel()) { + stackDataSet.addValue( + (double) objectdata.getTotalSize() + / GuiCommon.BINARY_PREFIX, new MapKey( + objectdata), labelStr.toString()); + heapUsage -= objectdata.getTotalSize(); + } + nameList.add(objectdata.getName()); + } + + if ((searchClass == null || searchClass.length == 0) + && (filterList == null || filterList.size() == 0)) { + stackDataSet.addValue((double) heapUsage + / GuiCommon.BINARY_PREFIX, new MapKey(0, "Others"), + labelStr.toString()); + } + + if (!before.equals(labelStr.toString()) && (k > 0) + && (rmv++ % k != 0)) { + hideLabel.add(labelStr.toString()); + } + // Sets the progress bound property. + setProgress(50 + 50 * (++per) / size); + } + + searchText.addList(nameList); + + JFreeChart chart = ChartFactory.createStackedAreaChart("", "", + "Usage(KB)", stackDataSet, PlotOrientation.VERTICAL, false, + true, true); + chart.setBackgroundPaint(Color.WHITE); + + CategoryPlot plot = chart.getCategoryPlot(); + plot.setBackgroundPaint(new Color(GuiCommon.getBgColor())); + hideCategoryLabel(plot.getDomainAxis(), hideLabel); + + GraphColorHelper.adjustColor(stackDataSet, chart.getPlot()); + usageChart = new ChartPanel(chart); + + usage.setComponent(usageChart, true); + + usageChart.addChartMouseListener(guimain); + } + + /** + * Hide unwanted items out of the X axis label. + * + * @param ca CategoryAxis + * @param hideLabel Hide item list + */ + private void hideCategoryLabel(final CategoryAxis ca, + final List<String> hideLabel) { + ca.setAxisLineVisible(false); + ca.setCategoryLabelPositions(CategoryLabelPositions + .createUpRotationLabelPositions(Math.PI / ANGLE)); + + for (String label : hideLabel) { + ca.setTickLabelPaint(label, new Color(0, 0, 0, 0)); + } + } + } +}
--- a/analyzer/src/jp/co/ntt/oss/heapstats/gui/FindDialog.java Mon Jun 24 11:42:50 2013 +0900 +++ b/analyzer/src/jp/co/ntt/oss/heapstats/gui/FindDialog.java Mon Jun 24 18:06:21 2013 -0700 @@ -1,161 +1,161 @@ -/* - * FindDialog.java - * Created on 2012/05/24 - * - * Copyright (C) 2011-2013 Nippon Telegraph and Telephone Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program 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 for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -package jp.co.ntt.oss.heapstats.gui; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import javax.swing.JButton; -import javax.swing.JComboBox; -import javax.swing.JDialog; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JTextArea; - -/** - * extends {@link JDialog}<br> - * implements {@link ActionListener}<br> - * <br> - * Search the contents of the log details. - */ -public class FindDialog extends JDialog implements - ActionListener { - /** serialVersionUID. */ - private static final long serialVersionUID = 2750747037965338897L; - - /** Text area that displays a detailed log. */ - private JTextArea textArea; - - /** Enter a search string. */ - private JComboBox word; - - /** Button is pressed, to conduct the search towards the end. */ - private JButton next; - - /** Close the dialog box to cancel the search. */ - private JButton cancel; - - /** - * Creates a modeless dialog with the specified Dialog as its owner. - * - * @param parent the owner Dialog from which the dialog is displayed or null - * if this dialog has no owner - * @param area Text area that displays a detailed log - */ - public FindDialog(final JDialog parent, final JTextArea area) { - super(parent); - setTitle(GuiCommon.getResources().getString(GuiCommon.FIND_TITLE)); - setSize(400, 90); - setResizable(false); - setLocationRelativeTo(parent); - - this.textArea = area; - - addComponent(); - } - - @Override - public final void actionPerformed(final ActionEvent e) { - Object eventSource = e.getSource(); - - if (eventSource.equals(next)) { - if (word.getSelectedIndex() < 0) { - word.addItem(word.getSelectedItem()); - } - find(); - } else if (eventSource.equals(cancel)) { - this.setVisible(false); - } - } - - /** - * Add the component to the screen. - */ - private void addComponent() { - JPanel main = new JPanel(); - main.setLayout(new BorderLayout(GuiCommon.BORDER_SIZE, - GuiCommon.BORDER_SIZE)); - add(main); - JLabel dammy = new JLabel(""); - dammy.setBackground(Color.RED); - - JPanel whatPanel = new JPanel(); - whatPanel.setLayout(new BorderLayout(GuiCommon.BORDER_SIZE, - GuiCommon.BORDER_SIZE)); - JLabel what = new JLabel(GuiCommon.getResources().getString( - GuiCommon.FIND_LABEL) - + " : "); - whatPanel.add(what, BorderLayout.NORTH); - - JPanel field = new JPanel(); - field.setLayout(new BorderLayout(GuiCommon.BORDER_SIZE, - GuiCommon.BORDER_SIZE)); - - word = new JComboBox(); - word.setEditable(true); - field.add(word, BorderLayout.NORTH); - - JPanel btn = new JPanel(); - btn.setLayout(new BorderLayout(GuiCommon.BORDER_SIZE, - GuiCommon.BORDER_SIZE)); - next = new JButton(GuiCommon.getResources().getString( - GuiCommon.FIND_NEXT)); - cancel = new JButton(GuiCommon.getResources().getString( - GuiCommon.FIND_CANCEL)); - next.addActionListener(this); - cancel.addActionListener(this); - btn.add(next, BorderLayout.NORTH); - btn.add(cancel, BorderLayout.SOUTH); - - main.add(dammy, BorderLayout.NORTH); - main.add(whatPanel, BorderLayout.WEST); - main.add(field, BorderLayout.CENTER); - main.add(btn, BorderLayout.EAST); - } - - /** - * Conduct the search of the specified string. - */ - private void find() { - Object inputWord = word.getSelectedItem(); - if (textArea.getText().isEmpty() || inputWord == null) { - return; - } - - int start = textArea.getText().indexOf( - inputWord.toString(), textArea.getSelectionEnd()); - if (start != -1) { - textArea.setFocusable(true); - textArea.setSelectionStart(start); - textArea.setSelectionEnd(start - + word.getSelectedItem().toString().length()); - } else { - GuiCommon.showMessage(this, GuiCommon.BASEI03, word - .getSelectedItem().toString(), - JOptionPane.INFORMATION_MESSAGE); - } - } -} +/* + * FindDialog.java + * Created on 2012/05/24 + * + * Copyright (C) 2011-2013 Nippon Telegraph and Telephone Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +package jp.co.ntt.oss.heapstats.gui; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JTextArea; + +/** + * extends {@link JDialog}<br> + * implements {@link ActionListener}<br> + * <br> + * Search the contents of the log details. + */ +public class FindDialog extends JDialog implements + ActionListener { + /** serialVersionUID. */ + private static final long serialVersionUID = 2750747037965338897L; + + /** Text area that displays a detailed log. */ + private JTextArea textArea; + + /** Enter a search string. */ + private JComboBox word; + + /** Button is pressed, to conduct the search towards the end. */ + private JButton next; + + /** Close the dialog box to cancel the search. */ + private JButton cancel; + + /** + * Creates a modeless dialog with the specified Dialog as its owner. + * + * @param parent the owner Dialog from which the dialog is displayed or null + * if this dialog has no owner + * @param area Text area that displays a detailed log + */ + public FindDialog(final JDialog parent, final JTextArea area) { + super(parent); + setTitle(GuiCommon.getResources().getString(GuiCommon.FIND_TITLE)); + setSize(400, 90); + setResizable(false); + setLocationRelativeTo(parent); + + this.textArea = area; + + addComponent(); + } + + @Override + public final void actionPerformed(final ActionEvent e) { + Object eventSource = e.getSource(); + + if (eventSource.equals(next)) { + if (word.getSelectedIndex() < 0) { + word.addItem(word.getSelectedItem()); + } + find(); + } else if (eventSource.equals(cancel)) { + this.setVisible(false); + } + } + + /** + * Add the component to the screen. + */ + private void addComponent() { + JPanel main = new JPanel(); + main.setLayout(new BorderLayout(GuiCommon.BORDER_SIZE, + GuiCommon.BORDER_SIZE)); + add(main); + JLabel dammy = new JLabel(""); + dammy.setBackground(Color.RED); + + JPanel whatPanel = new JPanel(); + whatPanel.setLayout(new BorderLayout(GuiCommon.BORDER_SIZE, + GuiCommon.BORDER_SIZE)); + JLabel what = new JLabel(GuiCommon.getResources().getString( + GuiCommon.FIND_LABEL) + + " : "); + whatPanel.add(what, BorderLayout.NORTH); + + JPanel field = new JPanel(); + field.setLayout(new BorderLayout(GuiCommon.BORDER_SIZE, + GuiCommon.BORDER_SIZE)); + + word = new JComboBox(); + word.setEditable(true); + field.add(word, BorderLayout.NORTH); + + JPanel btn = new JPanel(); + btn.setLayout(new BorderLayout(GuiCommon.BORDER_SIZE, + GuiCommon.BORDER_SIZE)); + next = new JButton(GuiCommon.getResources().getString( + GuiCommon.FIND_NEXT)); + cancel = new JButton(GuiCommon.getResources().getString( + GuiCommon.FIND_CANCEL)); + next.addActionListener(this); + cancel.addActionListener(this); + btn.add(next, BorderLayout.NORTH); + btn.add(cancel, BorderLayout.SOUTH); + + main.add(dammy, BorderLayout.NORTH); + main.add(whatPanel, BorderLayout.WEST); + main.add(field, BorderLayout.CENTER); + main.add(btn, BorderLayout.EAST); + } + + /** + * Conduct the search of the specified string. + */ + private void find() { + Object inputWord = word.getSelectedItem(); + if (textArea.getText().isEmpty() || inputWord == null) { + return; + } + + int start = textArea.getText().indexOf( + inputWord.toString(), textArea.getSelectionEnd()); + if (start != -1) { + textArea.setFocusable(true); + textArea.setSelectionStart(start); + textArea.setSelectionEnd(start + + word.getSelectedItem().toString().length()); + } else { + GuiCommon.showMessage(this, GuiCommon.BASEI03, word + .getSelectedItem().toString(), + JOptionPane.INFORMATION_MESSAGE); + } + } +}
--- a/analyzer/src/jp/co/ntt/oss/heapstats/gui/GCDialog.java Mon Jun 24 11:42:50 2013 +0900 +++ b/analyzer/src/jp/co/ntt/oss/heapstats/gui/GCDialog.java Mon Jun 24 18:06:21 2013 -0700 @@ -1,397 +1,397 @@ -/* - * GCDialog.java - * Created on 2011/10/13 - * - * Copyright (C) 2011-2013 Nippon Telegraph and Telephone Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program 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 for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -package jp.co.ntt.oss.heapstats.gui; - -import java.awt.Color; -import java.awt.Component; -import java.io.IOException; -import java.text.NumberFormat; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.List; - -import javax.swing.BorderFactory; -import javax.swing.Box; -import javax.swing.JDialog; -import javax.swing.JFrame; -import javax.swing.JOptionPane; -import javax.swing.JTable; -import javax.swing.SwingWorker; -import javax.swing.table.DefaultTableModel; - -import jp.co.ntt.oss.heapstats.container.SnapShot; -import jp.co.ntt.oss.heapstats.container.SnapShotHeader; -import jp.co.ntt.oss.heapstats.gui.snapshot.SnapShotReader; - -import org.jfree.chart.ChartFactory; -import org.jfree.chart.ChartPanel; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.axis.CategoryAxis; -import org.jfree.chart.axis.CategoryLabelPositions; -import org.jfree.chart.axis.NumberAxis; -import org.jfree.chart.plot.CategoryPlot; -import org.jfree.chart.plot.DatasetRenderingOrder; -import org.jfree.chart.plot.PlotOrientation; -import org.jfree.chart.renderer.category.LineAndShapeRenderer; -import org.jfree.chart.renderer.category.StackedAreaRenderer; -import org.jfree.data.category.DefaultCategoryDataset; - -/** - * extends {@link JDialog}<br> - * <br> - * Displays statistics for garbage collection. - */ -public class GCDialog extends JDialog { - /** serialVersionUID. */ - private static final long serialVersionUID = 3024831843243414334L; - - /** Angle of the axis labels. */ - private static final double ANGLE = 6.0; - - /** Statistics table Number of rows. */ - private static final int SUMMARY_ROW = 4; - - /** Statistics table Number of columns. */ - private static final int SUMMARY_COL = 2; - - /** Mainframe heapstats. */ - private GUIMain guimain; - - /** Main Component. */ - private Box comp = Box.createVerticalBox(); - - /** Minimum GC Time. */ - private long min = 0; - - /** Maximum GC Time. */ - private long max = 0; - - /** Panel of chart statistics. */ - private ChartPanel gcPanel; - - /** - * Create the 'SnapShot Data Dialog'. - * - * @param owner the owner Dialog from which the dialog is displayed or null - * if this dialog has no owner - */ - public GCDialog(final JFrame owner) { - super(owner); - guimain = (GUIMain) owner; - - setTitle(GuiCommon.getResources() - .getString(GuiCommon.TAB_TITLE_SUMMARY)); - setSize(GuiCommon.DEFAULT_DIALOG_WIDTH, GuiCommon.DEFAULT_DIALOG_HEIGHT); - setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); - setModal(false); - - comp.setBorder(BorderFactory.createEmptyBorder(GuiCommon.BORDER_SIZE, - GuiCommon.BORDER_SIZE, GuiCommon.BORDER_SIZE, - GuiCommon.BORDER_SIZE)); - setLocationByPlatform(true); - } - - /** - * Draw a pie chart in order of the heap usage of the snapshot. In addition, - * the table shows the heap usage for each object. - * - * @param diffOffsets file position and SnapShotReader - */ - public final void draw(final List<List<Object>> diffOffsets) { - clear(); - - GcWorker worker = new GcWorker(this, diffOffsets); - worker.execute(); - } - - /** - * Clear the Summary data. - */ - public final void clear() { - for (Component obj : comp.getComponents()) { - comp.remove(obj); - } - max = 0; - min = 0; - comp.setVisible(false); - } - - /** - * Return the component. - * - * @return Return the component - */ - public final Box getComp() { - return comp; - } - - /** - * Return the panel of chart statistics. - * - * @return Return the panel of chart statistics - */ - public final ChartPanel getGcPanel() { - return gcPanel; - } - - /** - * Sets the dialog component. - * - * @param value the Main Component - */ - public final void setComp(final Box value) { - comp = value; - add(comp); - } - - /** - * extends {@link SwingWorker}<br> - * <br> - * SwingWorker thread drawing done in the time-consuming process chart. - */ - class GcWorker extends SwingWorker<Object, Object> { - - /** file position and SnapShotReader. */ - private List<List<Object>> diffOffsets; - - /** the owner dialog. */ - private GCDialog dialog; - - /** - * Create a GcWorker. - * - * @param owner determines the Dialog in which the Dialog is displayed; - * if null, or if the parentComponent has no Dialog, a default - * Dialog is used - * @param offsets file position and SnapShotReader - */ - public GcWorker(final GCDialog owner, final List<List<Object>> offsets) { - diffOffsets = offsets; - dialog = owner; - } - - @Override - protected String doInBackground() { - try { - ExpansionContractionPanel chart = new ExpansionContractionPanel( - GuiCommon.getResources().getString( - GuiCommon.TITLE_STATISTICS)); - ExpansionContractionPanel summary = new ExpansionContractionPanel( - GuiCommon.getResources().getString( - GuiCommon.TITLE_SUMMARY)); - - comp.add(Box.createVerticalStrut(GuiCommon.BORDER_SIZE)); - comp.add(chart); - comp.revalidate(); - comp.add(Box.createVerticalStrut(GuiCommon.BORDER_SIZE)); - comp.add(summary); - comp.revalidate(); - - chart.setComponent(drawStatistictChart(), true); - - // Summary table - DefaultTableModel model = new DefaultTableModel(SUMMARY_ROW, - SUMMARY_COL); - JTable table = new JTable(model); - summary.setComponent(table, true); - - model.setRowCount(0); - Object[] row = new Object[2]; - - // SnapShot Count - NumberFormat nbf = NumberFormat.getIntegerInstance(); - row[0] = GuiCommon.getResources() - .getString(GuiCommon.SNAPCOUNT); - row[1] = nbf.format(diffOffsets.size()); - model.addRow(row); - - // Garbage collection Count - row[0] = GuiCommon.getResources().getString(GuiCommon.GCCOUNT); - List<Object> data = diffOffsets.get(diffOffsets.size() - 1); - SnapShot snapShot = ((SnapShotReader) data.get(1)) - .getSnapShot((Long) data.get(0)); - StringBuilder buf = new StringBuilder(); - buf.append(nbf.format(snapShot.getHeader().getFullCount() - + snapShot.getHeader().getYngCount())); - buf.append("(Full:"); - buf.append(nbf.format(snapShot.getHeader().getFullCount())); - buf.append(" , Young:"); - buf.append(nbf.format(snapShot.getHeader().getYngCount())); - buf.append(")"); - row[1] = buf.toString(); - model.addRow(row); - - // Latest Heap Usage - row[0] = GuiCommon.getResources().getString( - GuiCommon.LATEST_HEAP); - row[1] = nbf - .format((snapShot.getHeader().getNewHeap() + snapShot - .getHeader().getOldHeap()) - / GuiCommon.BINARY_PREFIX) - + " KB"; - model.addRow(row); - - // min gc time - row[0] = GuiCommon.getResources().getString( - GuiCommon.MIN_GCTIME); - row[1] = nbf.format(min) + " msec"; - model.addRow(row); - - // max gc time - row[0] = GuiCommon.getResources().getString( - GuiCommon.MAX_GCTIME); - row[1] = nbf.format(max) + " msec"; - model.addRow(row); - if (dialog.isVisible()) { - comp.setVisible(true); - } - } catch (IOException e) { - GuiCommon.showMessage(dialog.getParent(), GuiCommon.BASEE12, - JOptionPane.ERROR_MESSAGE); - e.printStackTrace(); - } catch (ClassNotFoundException e) { - GuiCommon.showMessage(dialog.getParent(), GuiCommon.BASEE12, - JOptionPane.ERROR_MESSAGE); - e.printStackTrace(); - } - - return null; - } - - /** - * The chart displays the statistics for Garbage collection. - * - * @return Return the ChartPanel - * @throws IOException If an I/O error has occurred. - * @throws ClassNotFoundException Class of a serialized object cannot be - * found. - */ - private ChartPanel drawStatistictChart() throws IOException, - ClassNotFoundException { - - DefaultCategoryDataset stackDataSet = new DefaultCategoryDataset(); - DefaultCategoryDataset usageDataSet = new DefaultCategoryDataset(); - DefaultCategoryDataset gctimeDataSet = new DefaultCategoryDataset(); - - StringBuilder labelStr = new StringBuilder(); - - SimpleDateFormat sdf = new SimpleDateFormat( - GuiCommon.CHART_DATE_FORMAT); - - List<String> removeLabel = new ArrayList<String>(); - - int i = 0; - int j = diffOffsets.size() / 10; - for (List<Object> data : diffOffsets) { - SnapShot snapShot = ((SnapShotReader) data.get(1)) - .getSnapShot((Long) data.get(0)); - - SnapShotHeader header = snapShot.getHeader(); - - String before = labelStr.toString(); - labelStr.delete(0, labelStr.length()); - labelStr.append(sdf.format(header.getSnapShotDate())); - - // set total heap size - stackDataSet.addValue((double) header.getTotalSize() - / GuiCommon.BINARY_PREFIX, GuiCommon.getResources() - .getString(GuiCommon.TOTAL_HEAP_SIZE), labelStr - .toString()); - // new heap usage - usageDataSet.addValue((double) header.getNewHeap() - / GuiCommon.BINARY_PREFIX, GuiCommon.getResources() - .getString(GuiCommon.NEW_HEAP), labelStr.toString()); - // old heap usage - usageDataSet.addValue((double) header.getOldHeap() - / GuiCommon.BINARY_PREFIX, GuiCommon.getResources() - .getString(GuiCommon.OLD_HEAP), labelStr.toString()); - // gc time - gctimeDataSet.addValue(header.getGcTime(), GuiCommon - .getResources().getString(GuiCommon.GCTIME), labelStr - .toString()); - - // min gc time - if (min == 0 - || (min > header.getGcTime() && header.getGcTime() > 0)) { - min = header.getGcTime(); - } - - // max gc time - if (max < header.getGcTime()) { - max = header.getGcTime(); - } - - if (!before.equals(labelStr.toString()) && (j > 0) - && (i++ % j != 0)) { - removeLabel.add(labelStr.toString()); - } - } - - JFreeChart chart = ChartFactory.createStackedAreaChart("", "", - "Usage(KB)", stackDataSet, PlotOrientation.VERTICAL, true, - true, true); - chart.setBackgroundPaint(Color.WHITE); - - CategoryPlot plot = chart.getCategoryPlot(); - plot.setBackgroundPaint(new Color(GuiCommon.getBgColor())); - - // Sets the DataSet heap usage(new + old). - plot.setDataset(1, usageDataSet); - - // Sets the DataSet gc processing time. - plot.setDataset(2, gctimeDataSet); - - // Sets vertical axis of the processing time value gc. - plot.mapDatasetToRangeAxis(2, 2); - - NumberAxis axis = new NumberAxis("Time(msec)"); - axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - // gc processing time : Integer value - plot.setRangeAxis(2, axis); - - StackedAreaRenderer renderer = new StackedAreaRenderer(); - - LineAndShapeRenderer gcrnderer = new LineAndShapeRenderer(); - gcrnderer.setSeriesShapesVisible(0, false); - - plot.setRenderer(1, renderer); - plot.setRenderer(2, gcrnderer); - plot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD); - - CategoryAxis ca = plot.getDomainAxis(); - ca.setCategoryLabelPositions(CategoryLabelPositions - .createUpRotationLabelPositions(Math.PI / ANGLE)); - - // clear the unwanted text. - for (String label : removeLabel) { - ca.setTickLabelPaint(label, new Color(0, 0, 0, 0)); - } - - gcPanel = new ChartPanel(chart); - - gcPanel.addChartMouseListener(guimain); - - return gcPanel; - } - } -} +/* + * GCDialog.java + * Created on 2011/10/13 + * + * Copyright (C) 2011-2013 Nippon Telegraph and Telephone Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +package jp.co.ntt.oss.heapstats.gui; + +import java.awt.Color; +import java.awt.Component; +import java.io.IOException; +import java.text.NumberFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JOptionPane; +import javax.swing.JTable; +import javax.swing.SwingWorker; +import javax.swing.table.DefaultTableModel; + +import jp.co.ntt.oss.heapstats.container.SnapShot; +import jp.co.ntt.oss.heapstats.container.SnapShotHeader; +import jp.co.ntt.oss.heapstats.gui.snapshot.SnapShotReader; + +import org.jfree.chart.ChartFactory; +import org.jfree.chart.ChartPanel; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.axis.CategoryAxis; +import org.jfree.chart.axis.CategoryLabelPositions; +import org.jfree.chart.axis.NumberAxis; +import org.jfree.chart.plot.CategoryPlot; +import org.jfree.chart.plot.DatasetRenderingOrder; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.renderer.category.LineAndShapeRenderer; +import org.jfree.chart.renderer.category.StackedAreaRenderer; +import org.jfree.data.category.DefaultCategoryDataset; + +/** + * extends {@link JDialog}<br> + * <br> + * Displays statistics for garbage collection. + */ +public class GCDialog extends JDialog { + /** serialVersionUID. */ + private static final long serialVersionUID = 3024831843243414334L; + + /** Angle of the axis labels. */ + private static final double ANGLE = 6.0; + + /** Statistics table Number of rows. */ + private static final int SUMMARY_ROW = 4; + + /** Statistics table Number of columns. */ + private static final int SUMMARY_COL = 2; + + /** Mainframe heapstats. */ + private GUIMain guimain; + + /** Main Component. */ + private Box comp = Box.createVerticalBox(); + + /** Minimum GC Time. */ + private long min = 0; + + /** Maximum GC Time. */ + private long max = 0; + + /** Panel of chart statistics. */ + private ChartPanel gcPanel; + + /** + * Create the 'SnapShot Data Dialog'. + * + * @param owner the owner Dialog from which the dialog is displayed or null + * if this dialog has no owner + */ + public GCDialog(final JFrame owner) { + super(owner); + guimain = (GUIMain) owner; + + setTitle(GuiCommon.getResources() + .getString(GuiCommon.TAB_TITLE_SUMMARY)); + setSize(GuiCommon.DEFAULT_DIALOG_WIDTH, GuiCommon.DEFAULT_DIALOG_HEIGHT); + setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); + setModal(false); + + comp.setBorder(BorderFactory.createEmptyBorder(GuiCommon.BORDER_SIZE, + GuiCommon.BORDER_SIZE, GuiCommon.BORDER_SIZE, + GuiCommon.BORDER_SIZE)); + setLocationByPlatform(true); + } + + /** + * Draw a pie chart in order of the heap usage of the snapshot. In addition, + * the table shows the heap usage for each object. + * + * @param diffOffsets file position and SnapShotReader + */ + public final void draw(final List<List<Object>> diffOffsets) { + clear(); + + GcWorker worker = new GcWorker(this, diffOffsets); + worker.execute(); + } + + /** + * Clear the Summary data. + */ + public final void clear() { + for (Component obj : comp.getComponents()) { + comp.remove(obj); + } + max = 0; + min = 0; + comp.setVisible(false); + } + + /** + * Return the component. + * + * @return Return the component + */ + public final Box getComp() { + return comp; + } + + /** + * Return the panel of chart statistics. + * + * @return Return the panel of chart statistics + */ + public final ChartPanel getGcPanel() { + return gcPanel; + } + + /** + * Sets the dialog component. + * + * @param value the Main Component + */ + public final void setComp(final Box value) { + comp = value; + add(comp); + } + + /** + * extends {@link SwingWorker}<br> + * <br> + * SwingWorker thread drawing done in the time-consuming process chart. + */ + class GcWorker extends SwingWorker<Object, Object> { + + /** file position and SnapShotReader. */ + private List<List<Object>> diffOffsets; + + /** the owner dialog. */ + private GCDialog dialog; + + /** + * Create a GcWorker. + * + * @param owner determines the Dialog in which the Dialog is displayed; + * if null, or if the parentComponent has no Dialog, a default + * Dialog is used + * @param offsets file position and SnapShotReader + */ + public GcWorker(final GCDialog owner, final List<List<Object>> offsets) { + diffOffsets = offsets; + dialog = owner; + } + + @Override + protected String doInBackground() { + try { + ExpansionContractionPanel chart = new ExpansionContractionPanel( + GuiCommon.getResources().getString( + GuiCommon.TITLE_STATISTICS)); + ExpansionContractionPanel summary = new ExpansionContractionPanel( + GuiCommon.getResources().getString( + GuiCommon.TITLE_SUMMARY)); + + comp.add(Box.createVerticalStrut(GuiCommon.BORDER_SIZE)); + comp.add(chart); + comp.revalidate(); + comp.add(Box.createVerticalStrut(GuiCommon.BORDER_SIZE)); + comp.add(summary); + comp.revalidate(); + + chart.setComponent(drawStatistictChart(), true); + + // Summary table + DefaultTableModel model = new DefaultTableModel(SUMMARY_ROW, + SUMMARY_COL); + JTable table = new JTable(model); + summary.setComponent(table, true); + + model.setRowCount(0); + Object[] row = new Object[2]; + + // SnapShot Count + NumberFormat nbf = NumberFormat.getIntegerInstance(); + row[0] = GuiCommon.getResources() + .getString(GuiCommon.SNAPCOUNT); + row[1] = nbf.format(diffOffsets.size()); + model.addRow(row); + + // Garbage collection Count + row[0] = GuiCommon.getResources().getString(GuiCommon.GCCOUNT); + List<Object> data = diffOffsets.get(diffOffsets.size() - 1); + SnapShot snapShot = ((SnapShotReader) data.get(1)) + .getSnapShot((Long) data.get(0)); + StringBuilder buf = new StringBuilder(); + buf.append(nbf.format(snapShot.getHeader().getFullCount() + + snapShot.getHeader().getYngCount())); + buf.append("(Full:"); + buf.append(nbf.format(snapShot.getHeader().getFullCount())); + buf.append(" , Young:"); + buf.append(nbf.format(snapShot.getHeader().getYngCount())); + buf.append(")"); + row[1] = buf.toString(); + model.addRow(row); + + // Latest Heap Usage + row[0] = GuiCommon.getResources().getString( + GuiCommon.LATEST_HEAP); + row[1] = nbf + .format((snapShot.getHeader().getNewHeap() + snapShot + .getHeader().getOldHeap()) + / GuiCommon.BINARY_PREFIX) + + " KB"; + model.addRow(row); + + // min gc time + row[0] = GuiCommon.getResources().getString( + GuiCommon.MIN_GCTIME); + row[1] = nbf.format(min) + " msec"; + model.addRow(row); + + // max gc time + row[0] = GuiCommon.getResources().getString( + GuiCommon.MAX_GCTIME); + row[1] = nbf.format(max) + " msec"; + model.addRow(row); + if (dialog.isVisible()) { + comp.setVisible(true); + } + } catch (IOException e) { + GuiCommon.showMessage(dialog.getParent(), GuiCommon.BASEE12, + JOptionPane.ERROR_MESSAGE); + e.printStackTrace(); + } catch (ClassNotFoundException e) { + GuiCommon.showMessage(dialog.getParent(), GuiCommon.BASEE12, + JOptionPane.ERROR_MESSAGE); + e.printStackTrace(); + } + + return null; + } + + /** + * The chart displays the statistics for Garbage collection. + * + * @return Return the ChartPanel + * @throws IOException If an I/O error has occurred. + * @throws ClassNotFoundException Class of a serialized object cannot be + * found. + */ + private ChartPanel drawStatistictChart() throws IOException, + ClassNotFoundException { + + DefaultCategoryDataset stackDataSet = new DefaultCategoryDataset(); + DefaultCategoryDataset usageDataSet = new DefaultCategoryDataset(); + DefaultCategoryDataset gctimeDataSet = new DefaultCategoryDataset(); + + StringBuilder labelStr = new StringBuilder(); + + SimpleDateFormat sdf = new SimpleDateFormat( + GuiCommon.CHART_DATE_FORMAT); + + List<String> removeLabel = new ArrayList<String>(); + + int i = 0; + int j = diffOffsets.size() / 10; + for (List<Object> data : diffOffsets) { + SnapShot snapShot = ((SnapShotReader) data.get(1)) + .getSnapShot((Long) data.get(0)); + + SnapShotHeader header = snapShot.getHeader(); + + String before = labelStr.toString(); + labelStr.delete(0, labelStr.length()); + labelStr.append(sdf.format(header.getSnapShotDate())); + + // set total heap size + stackDataSet.addValue((double) header.getTotalSize() + / GuiCommon.BINARY_PREFIX, GuiCommon.getResources() + .getString(GuiCommon.TOTAL_HEAP_SIZE), labelStr + .toString()); + // new heap usage + usageDataSet.addValue((double) header.getNewHeap() + / GuiCommon.BINARY_PREFIX, GuiCommon.getResources() + .getString(GuiCommon.NEW_HEAP), labelStr.toString()); + // old heap usage + usageDataSet.addValue((double) header.getOldHeap() + / GuiCommon.BINARY_PREFIX, GuiCommon.getResources() + .getString(GuiCommon.OLD_HEAP), labelStr.toString()); + // gc time + gctimeDataSet.addValue(header.getGcTime(), GuiCommon + .getResources().getString(GuiCommon.GCTIME), labelStr + .toString()); + + // min gc time + if (min == 0 + || (min > header.getGcTime() && header.getGcTime() > 0)) { + min = header.getGcTime(); + } + + // max gc time + if (max < header.getGcTime()) { + max = header.getGcTime(); + } + + if (!before.equals(labelStr.toString()) && (j > 0) + && (i++ % j != 0)) { + removeLabel.add(labelStr.toString()); + } + } + + JFreeChart chart = ChartFactory.createStackedAreaChart("", "", + "Usage(KB)", stackDataSet, PlotOrientation.VERTICAL, true, + true, true); + chart.setBackgroundPaint(Color.WHITE); + + CategoryPlot plot = chart.getCategoryPlot(); + plot.setBackgroundPaint(new Color(GuiCommon.getBgColor())); + + // Sets the DataSet heap usage(new + old). + plot.setDataset(1, usageDataSet); + + // Sets the DataSet gc processing time. + plot.setDataset(2, gctimeDataSet); + + // Sets vertical axis of the processing time value gc. + plot.mapDatasetToRangeAxis(2, 2); + + NumberAxis axis = new NumberAxis("Time(msec)"); + axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); + // gc processing time : Integer value + plot.setRangeAxis(2, axis); + + StackedAreaRenderer renderer = new StackedAreaRenderer(); + + LineAndShapeRenderer gcrnderer = new LineAndShapeRenderer(); + gcrnderer.setSeriesShapesVisible(0, false); + + plot.setRenderer(1, renderer); + plot.setRenderer(2, gcrnderer); + plot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD); + + CategoryAxis ca = plot.getDomainAxis(); + ca.setCategoryLabelPositions(CategoryLabelPositions + .createUpRotationLabelPositions(Math.PI / ANGLE)); + + // clear the unwanted text. + for (String label : removeLabel) { + ca.setTickLabelPaint(label, new Color(0, 0, 0, 0)); + } + + gcPanel = new ChartPanel(chart); + + gcPanel.addChartMouseListener(guimain); + + return gcPanel; + } + } +}
--- a/analyzer/src/jp/co/ntt/oss/heapstats/gui/GuiCommon.java Mon Jun 24 11:42:50 2013 +0900 +++ b/analyzer/src/jp/co/ntt/oss/heapstats/gui/GuiCommon.java Mon Jun 24 18:06:21 2013 -0700 @@ -1,694 +1,694 @@ -/* - * GuiCommon.java - * Created on 2011/09/08 - * - * Copyright (C) 2011-2013 Nippon Telegraph and Telephone Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program 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 for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -package jp.co.ntt.oss.heapstats.gui; - -import java.awt.Component; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Locale; -import java.util.Properties; -import java.util.ResourceBundle; - -import javax.swing.JOptionPane; - -/** - * Define a common resource to be used in heapstats. - */ -public final class GuiCommon { - - /** Size column lists the object's color. */ - public static final int COL_SIZE_COLOR = 10; - - /** Size column lists the class name. */ - public static final int COL_SIZE_CLASSNAME = 200; - - /** Binary prefix. */ - public static final int BINARY_PREFIX = 1024; - - /** Menu-File key. */ - public static final String MENU_FILE = "file"; - - /** Menu-File-Log File Open key. */ - public static final String MENU_FILE_LOGOPEN = "logopen"; - - /** Menu-File-Open key. */ - public static final String MENU_FILE_OPEN = "open"; - - /** Menu-File-Exit key. */ - public static final String MENU_FILE_EXIT = "exit"; - - /** Menu-Option key. */ - public static final String MENU_OPTION = "option"; - - /** Menu-Option-Tab key. */ - public static final String MENU_OPTION_TAB = "tabbar"; - - /** Menu-Option-Ranking Graph Level key. */ - public static final String MENU_OPTION_RANKLEVEL = "rank"; - - /** Menu-Option-Write to CSV key. */ - public static final String MENU_OPTION_CSV = "csv"; - - /** Menu-Option-CSV-Heap Usage key. */ - public static final String MENU_OPTION_CSVHEAP = "csvheap"; - - /** Menu-Option-CSV-GC statistics key. */ - public static final String MENU_OPTION_CSVGC = "csvstatistics"; - - /** Menu-Option-CSV-all key. */ - public static final String MENU_OPTION_CSVALL = "csvall"; - - /** Menu-Option-CSV-selected key. */ - public static final String MENU_OPTION_CSVSELECTED = "csvselected"; - - /** Menu-help key. */ - public static final String MENU_HELP = "help"; - - /** Menu-help-how to use key. */ - public static final String MENU_USE = "howtouse"; - - /** Menu-help-version key. */ - public static final String MENU_HELP_VERSION = "version"; - - /** Window title for the version key. */ - public static final String VERSION_DIALOG_TITLE = "versiontitle"; - - /** Manual for simple text file name. */ - public static final String HOWTO_TEXT = "howtotext"; - - /** The key to get the tab title of Statistics GC. */ - public static final String TAB_TITLE_SUMMARY = "tabsummary"; - - /** The key to get the tab title of Delta. */ - public static final String TAB_TITLE_DELA = "tabdelta"; - - /** The key to get the tab title of SnapShot. */ - public static final String TAB_TITLE_SNAPSHOT = "tabsnapshot"; - - /** The key to get the tab title of Resource. */ - public static final String TAB_TITLE_RESOUCE = "tabresouce"; - - /** The key to get the tab title of Log Collect. */ - public static final String TAB_TITLE_LOG = "tablogcollection"; - - /** Ranking Settings dialog label title. */ - public static final String RANK_LEVEL = "ranktitle"; - - /** The key to get the tab title of Log Collect. */ - public static final String MAIN_TAB_LOGCOLLECT = "maintablog"; - - /** The key to get the tab title of SnapShot. */ - public static final String MAIN_TAB_SNAPSHOT = "maintabsnapshot"; - - /** Select Log Main Title. */ - public static final String TITLE_LOG = "titellog"; - - /** LOG SELECT Button. */ - public static final String BUTTON_LOG_SELECT = "logselectbutton"; - - // SELECT DATA - /** SELECT DATA MAIN TITLE. */ - public static final String TITLE_MAIN = "titlemain"; - - /** SELECT DATA BUTTON. */ - public static final String SELECT_DATA = "selectdata"; - - /** SELECT RAGE LABEL. */ - public static final String SELECT_RANGE = "selectrange"; - - // Summary Data - /** The accordion panel title of the chart statistics. */ - public static final String TITLE_STATISTICS = "titlestatistics"; - - /** the row key. */ - public static final String TOTAL_HEAP_SIZE = "totalheapsize"; - - /** the row key. */ - public static final String NEW_HEAP = "newheapsize"; - - /** the row key. */ - public static final String OLD_HEAP = "oldheapsize"; - - /** the row key. */ - public static final String GCTIME = "gctime"; - - /** the table key. */ - public static final String TITLE_SUMMARY = "titlesummary"; - - /** the table key. */ - public static final String SNAPCOUNT = "snapcount"; - - /** the table key. */ - public static final String GCCOUNT = "gccount"; - - /** the table key. */ - public static final String LATEST_HEAP = "latestheapusage"; - - /** the table key. */ - public static final String MIN_GCTIME = "mingctime"; - - /** the table key. */ - public static final String MAX_GCTIME = "maxgctime"; - - // Delta Data - /** The accordion panel title of the chart ranking(size). */ - public static final String TITLE_SIZE_DELTE = "titledeltasize"; - - /** The accordion panel title of the chart ranking(instance). */ - public static final String TITLE_INSTANCE_DELTE = "titledeltainstance"; - - /** The accordion panel title of the chart delta(size). */ - public static final String TITLE_SIZE_AREA = "titleareachartsize"; - - /** The accordion panel title of the chart delta(instance). */ - public static final String TITLE_INSTANCE_AREA = "titleareachartinstance"; - - /** The accordion panel title of the objects list. */ - public static final String TITLE_OBJECTLIST = "titleobjectslist"; - - /** the table title of the object name. */ - public static final String OBJECTLIST_NAME = "name"; - - /** the table title of the object instances. */ - public static final String OBJECTLIST_INSTANCE = "instances"; - - /** the table title of the heap usage. */ - public static final String OBJECTLIST_SIZE = "size"; - - /** Class Filter Label title. */ - public static final String CLASS_FILTER_LABEL_TITLE = "titlefilter"; - - /** Class Filter ADD Button. */ - public static final String CLASS_FILTER_ADD = "addfilter"; - - /** Class Search Label title. */ - public static final String CLASS_SEARCH_LABEL_TITLE = "titlesearch"; - - /** Exclude Key. */ - public static final String CLASS_FILTER_EXCLUDE = "exclude"; - - /** Filter Name Key. */ - public static final String CLASS_FILTER_FILENAME = "filtername"; - - /** Sort button(instance). */ - public static final String SORT_INSTANCE = "sortinstance"; - - /** Sort button(heap usage). */ - public static final String SORT_SIZE = "sortsize"; - - // SnapShot Data - /** The accordion panel title of the SnapShot Data. */ - public static final String TITLE_SNAPSHOT = "titlesnapshot"; - - /** The accordion panel title of the chart heap usage. */ - public static final String TITLE_PIECHART = "titlepiechart"; - - /** the table key. */ - public static final String SNAPSHOTINFO_DATE = "date"; - - /** the table key. */ - public static final String SNAPSHOTINFO_ENTRYIES = "entries"; - - /** the table key. */ - public static final String SNAPSHOTINFO_HEAP = "totalheapusage"; - - /** the table key. */ - public static final String SNAPSHOTINFO_CAUSE = "sscause"; - - /** the table key. */ - public static final String SNAPSHOTINFO_GCCAUSE = "gccause"; - - /** The format of the time you draw on screen. */ - public static final String DATE_FORMAT = "yyyyMMdd HH:mm:ss"; - - /** The format of the time you draw on screen. */ - public static final String CHART_DATE_FORMAT = "MMdd HH:mm:ss.SSS"; - - // Log Data - /** The key to get the tab title of Resource. */ - public static final String TAB_RESOURCE_SUMMARY = "tabresource"; - - /** The key to get the tab title of LogDetail. */ - public static final String TAB_LOG_DETAIL = "tablogdetail"; - - /** The accordion panel title of the Resource reports. */ - public static final String TITLE_RESOURCE_REPORT = "titleresource"; - - /** The accordion panel title of the Process reports. */ - public static final String TITLE_THREAD_SUMMARY = "processreports"; - - /** The accordion panel title of the Resource reports. */ - public static final String TITLE_RESOURCE = "titleresouce"; - - /** Name javaCPU chart. */ - public static final String GRAPH_JAVA_CPU = "graphjavacpu"; - - /** Name systemCPU chart. */ - public static final String GRAPH_SYSTEM_CPU = "graphsyscpu"; - - /** Name java Memory chart. */ - public static final String GRAPH_JAVA_MEMORY = "graphjavamem"; - - /** Name threads chart. */ - public static final String GRAPH_THREADS = "graphthread"; - - /** Field name of table. */ - public static final String ITEM_CPU_AVERAGE = "cpuave"; - - /** Field name of table. */ - public static final String ITEM_CPU_PEAK = "cpupeak"; - - /** Field name of table. */ - public static final String ITEM_VSZ_AVERAGE = "vszave"; - - /** Field name of table. */ - public static final String ITEM_VSZ_PEAK = "vszpeak"; - - /** Field name of table. */ - public static final String ITEM_RSS_AVERAGE = "rssave"; - - /** Field name of table. */ - public static final String ITEM_RSS_PEAK = "rsspeak"; - - /** The name of the Log Detail Data button. */ - public static final String NEXT_BUTTON = "nextbutton"; - - /** The name of the Log Detail Data button. */ - public static final String PREV_BUTTON = "prevbutton"; - - /** The Log Detail Data Table Header Name. */ - public static final String LOG_HEAD_ITEM = "tableheaditem"; - - /** The Log Detail Data Table Header Name. */ - public static final String LOG_HEAD_DATA = "tableheaddata"; - - /** POPUPMENU-CUT key. */ - public static final String POPUP_CUT = "popupcut"; - - /** POPUPMENU-COPY key. */ - public static final String POPUP_COPY = "popupcopy"; - - /** POPUPMENU-PASTE key. */ - public static final String POPUP_PASTE = "popuppaste"; - - /** POPUPMENU-FIND key. */ - public static final String POPUP_FIND = "popupfind"; - - // Find Dialog - /** The key for obtain the title of the search dialog. */ - public static final String FIND_TITLE = "findtitle"; - - /** The key for obtain the label of the search dialog. */ - public static final String FIND_LABEL = "findlabel"; - - /** The key for obtain the name of the button of the search dialog. */ - public static final String FIND_NEXT = "findnext"; - - /** The key for obtain the name of the button of the search dialog. */ - public static final String FIND_CANCEL = "findcancel"; - - // Message - /** Start the filter. */ - public static final String BASEI01 = "base-i-01"; - - /** Complete output of the CSV. */ - public static final String BASEI02 = "base-i-02"; - - /** "%s" string can not be found in the rear. */ - public static final String BASEI03 = "base-i-03"; - - /** Failed to load heapstats.properties. Use the default values. */ - public static final String BASEW01 = "base-w-01"; - - /** Please try again after waiting some time for processing. */ - public static final String BASEW02 = "base-w-02"; - - /** Please input numeric value. */ - public static final String BASEE01 = "base-e-01"; - - /** Please input positive value. */ - public static final String BASEE02 = "base-e-02"; - - /** Please open SnapShot file. */ - public static final String BASEE03 = "base-e-03"; - - /** Please specify the period. */ - public static final String BASEE05 = "base-e-05"; - - /** Please select the time period again. */ - public static final String BASEE06 = "base-e-06"; - - /** Start and end are the same. */ - public static final String BASEE07 = "base-e-07"; - - /** Failed to load the file. */ - public static final String BASEE08 = "base-e-08"; - - /** Couldn't find library directory. (%) */ - public static final String BASEE09 = "base-e-09"; - - /** Duplicate filter name it, we canceled the loading. */ - public static final String BASEE10 = "base-e-10"; - - /** An error occurred while loading a filter definition file. (%) */ - public static final String BASEE11 = "base-e-11"; - - /** [SnapShot Data] failed to draw. */ - public static final String BASEE12 = "base-e-12"; - - /** [Delta Data] failed to draw. */ - public static final String BASEE13 = "base-e-13"; - - /** [Summary Data] failed to draw. */ - public static final String BASEE14 = "base-e-14"; - - /** Failed to output CSV. [%s] */ - public static final String BASEE15 = "base-e-15"; - - /** Error occurred during startup. Please reboot. */ - public static final String BASEE16 = "base-e-16"; - - /** Failed to write the properties file. */ - public static final String BASEE17 = "base-e-17"; - - /** Failed to open the file. */ - public static final String BASEE18 = "base-e-18"; - - /** Failed to decode the file. */ - public static final String BASEE19 = "base-e-19"; - - /** [Resource Data] failed to draw. */ - public static final String BASEE20 = "base-e-20"; - - /** Couldn't find the library. (%) */ - public static final String BASEE21 = "base-e-21"; - - /** Default Frame Width. */ - public static final int DEFAULT_FRAME_WIDTH = 800; - - /** Default Frame Height. */ - public static final int DEFAULT_FRAME_HEIGHT = 600; - - /** Default width. */ - public static final int DEFAULT_DIALOG_WIDTH = 600; - - /** Default Height. */ - public static final int DEFAULT_DIALOG_HEIGHT = 400; - - /** Replacement character. */ - public static final String REPLACEMENT_CHAR = "%s"; - - /** Analyzer window title. */ - public static final String ANALYZER_TITLE = "HeapStats Analyzer"; - - /** Border size. */ - public static final int BORDER_SIZE = 5; - - /** Thread dump file name of the agent has collected. */ - public static final String THREAD_DUNM_FILE = "threaddump.txt"; - - /** Split character to split the file path for multiple. */ - public static final String SPLIT_CHARACTER = ";"; - - /** Default Language.Default is English. */ - private static final String DEFAULT_LANGUAGE = "en"; - - /** Default Ranking Level.Default is 5. */ - private static final int DEFAULT_RANKING = 5; - - /** Rename the class path to the screen. Default is false. */ - private static final boolean DEFAULT_REPLACE = false; - - /** the HeapStatus property file name. */ - private static final String CONFIG_HEAPSTATS = "heapstats.properties"; - - /** Default Language. */ - private static String language = DEFAULT_LANGUAGE; - - /** Default Ranking Level. */ - private static int rankLevel = DEFAULT_RANKING; - - /** the current directory. */ - private static File currentDir; - - /** Rename the class path to the screen. Renaming is true. */ - private static boolean classRename = DEFAULT_REPLACE; - - /** Rename the class path to the screen. Renaming is true. */ - private static String logfiles = ""; - - /** Rename the class path to the screen. Renaming is true. */ - private static String socketend = ""; - - /** Background color of the chart. */ - private static int bgColor = 0; - - /** Multilingual Resources. */ - private static ResourceBundle resources = ResourceBundle.getBundle( - "HeapStatsResources", new Locale(language)); - - /** The properties file heapstats. */ - private static Properties prop = new Properties(); - - /** - * Don't let anyone instantiate this class. - */ - private GuiCommon() { - } - - /** - * Load the properties file. - * - * @throws Exception if the file does not exist, is a directory rather than - * a regular file, or for some other reason cannot be opened for - * reading. - */ - public static void load() throws Exception { - InputStream inputStream = null; - try { - File pp = new File(CONFIG_HEAPSTATS); - inputStream = new FileInputStream(pp); - prop.load(inputStream); - language = prop.getProperty("language"); - if (language == null - || (!language.equals(DEFAULT_LANGUAGE) && !language - .equals("ja"))) { - throw new Exception(); - } - rankLevel = Integer.decode(prop.getProperty("ranklevel")); - if (rankLevel < 1) { - throw new Exception(); - } - classRename = Boolean.parseBoolean(prop.getProperty("replace")); - if (prop.getProperty("defaultdir") != null) { - currentDir = new File(prop.getProperty("defaultdir")); - } - logfiles = prop.getProperty("logfile"); - socketend = prop.getProperty("socketend"); - bgColor = Integer.decode(prop.getProperty("bgcolor")); - } catch (Exception e) { - language = DEFAULT_LANGUAGE; - rankLevel = DEFAULT_RANKING; - classRename = DEFAULT_REPLACE; - logfiles = ""; - socketend = ""; - currentDir = null; - bgColor = 0; - - throw e; - } finally { - if (inputStream != null) { - inputStream.close(); - } - } - resources = ResourceBundle.getBundle("HeapStatsResources", new Locale( - language)); - } - - /** - * Return the Language. - * - * @return Return the Language - */ - public static String getLanguage() { - return language; - } - - /** - * Return the Ranking level. - * - * @return Return the Ranking level. - */ - public static int getRankLevel() { - return rankLevel; - } - - /** - * Sets a Ranking level. - * - * @param rank ranking - * @throws IOException if an I/O error occurs. - */ - public static void setRankLevel(final int rank) throws IOException { - OutputStream outputstream = null; - try { - outputstream = new FileOutputStream(CONFIG_HEAPSTATS); - prop.setProperty("ranklevel", Integer.toString(rank)); - prop.store(outputstream, null); - rankLevel = rank; - } finally { - if (outputstream != null) { - outputstream.close(); - } - } - } - - /** - * Returns the class path to rename. - * - * @return Returns the class path to rename. - */ - public static boolean getClassRename() { - return classRename; - } - - /** - * Return the List of log file to read. - * - * @return Return the List of log file to read - */ - public static String getLogfiles() { - return logfiles; - } - - /** - * Return the List of socket file. - * - * @return Return the List of socket file - */ - public static String getSocketend() { - return socketend; - } - - /** - * Return the Background color of the chart. - * - * @return Return the Background color of the chart - */ - public static int getBgColor() { - return bgColor; - } - - /** - * Return the resource. - * - * @return Return the resource - */ - public static ResourceBundle getResources() { - return resources; - } - - /** - * Return the current directory. - * - * @return Return the current directory - */ - public static File getCurrentDir() { - return currentDir; - } - - /** - * Sets the current directory. - * - * @param directory current directory - * @throws IOException if writing this property list to the specified output - * stream throws an IOException. - */ - public static void setCurrentDir(final File directory) throws IOException { - OutputStream outputstream = null; - try { - currentDir = directory; - outputstream = new FileOutputStream(CONFIG_HEAPSTATS); - prop.setProperty("defaultdir", directory.getAbsolutePath()); - prop.store(outputstream, null); - } finally { - if (outputstream != null) { - outputstream.close(); - } - } - } - - /** - * Brings up a dialog that displays a message using a default icon - * determined by the messageType parameter. - * - * @param component determines the Frame in which the dialog is displayed; - * if null, or if the parentComponent has no Frame, a default Frame - * is used - * @param messageId the Object to display id - * @param messageType the type of message to be displayed: ERROR_MESSAGE, - * INFORMATION_MESSAGE, WARNING_MESSAGE, QUESTION_MESSAGE, or - * PLAIN_MESSAGE - */ - public static void showMessage(final Component component, - final String messageId, final int messageType) { - try { - JOptionPane - .showMessageDialog(component, - resources.getString(messageId), ANALYZER_TITLE, - messageType); - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * Brings up a dialog that displays a message using a default icon - * determined by the messageType parameter. - * - * @param component determines the Frame in which the dialog is displayed; - * if null, or if the parentComponent has no Frame, a default Frame - * is used - * @param messageId the Object to display id - * @param replacement The replacement sequence of char values - * @param messageType the type of message to be displayed: ERROR_MESSAGE, - * INFORMATION_MESSAGE, WARNING_MESSAGE, QUESTION_MESSAGE, or - * PLAIN_MESSAGE - */ - public static void showMessage(final Component component, - final String messageId, final String replacement, - final int messageType) { - try { - JOptionPane.showMessageDialog( - component, - resources.getString(messageId).replace(REPLACEMENT_CHAR, - replacement), ANALYZER_TITLE, messageType); - } catch (Exception e) { - e.printStackTrace(); - } - } -} +/* + * GuiCommon.java + * Created on 2011/09/08 + * + * Copyright (C) 2011-2013 Nippon Telegraph and Telephone Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +package jp.co.ntt.oss.heapstats.gui; + +import java.awt.Component; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Locale; +import java.util.Properties; +import java.util.ResourceBundle; + +import javax.swing.JOptionPane; + +/** + * Define a common resource to be used in heapstats. + */ +public final class GuiCommon { + + /** Size column lists the object's color. */ + public static final int COL_SIZE_COLOR = 10; + + /** Size column lists the class name. */ + public static final int COL_SIZE_CLASSNAME = 200; + + /** Binary prefix. */ + public static final int BINARY_PREFIX = 1024; + + /** Menu-File key. */ + public static final String MENU_FILE = "file"; + + /** Menu-File-Log File Open key. */ + public static final String MENU_FILE_LOGOPEN = "logopen"; + + /** Menu-File-Open key. */ + public static final String MENU_FILE_OPEN = "open"; + + /** Menu-File-Exit key. */ + public static final String MENU_FILE_EXIT = "exit"; + + /** Menu-Option key. */ + public static final String MENU_OPTION = "option"; + + /** Menu-Option-Tab key. */ + public static final String MENU_OPTION_TAB = "tabbar"; + + /** Menu-Option-Ranking Graph Level key. */ + public static final String MENU_OPTION_RANKLEVEL = "rank"; + + /** Menu-Option-Write to CSV key. */ + public static final String MENU_OPTION_CSV = "csv"; + + /** Menu-Option-CSV-Heap Usage key. */ + public static final String MENU_OPTION_CSVHEAP = "csvheap"; + + /** Menu-Option-CSV-GC statistics key. */ + public static final String MENU_OPTION_CSVGC = "csvstatistics"; + + /** Menu-Option-CSV-all key. */ + public static final String MENU_OPTION_CSVALL = "csvall"; + + /** Menu-Option-CSV-selected key. */ + public static final String MENU_OPTION_CSVSELECTED = "csvselected"; + + /** Menu-help key. */ + public static final String MENU_HELP = "help"; + + /** Menu-help-how to use key. */ + public static final String MENU_USE = "howtouse"; + + /** Menu-help-version key. */ + public static final String MENU_HELP_VERSION = "version"; + + /** Window title for the version key. */ + public static final String VERSION_DIALOG_TITLE = "versiontitle"; + + /** Manual for simple text file name. */ + public static final String HOWTO_TEXT = "howtotext"; + + /** The key to get the tab title of Statistics GC. */ + public static final String TAB_TITLE_SUMMARY = "tabsummary"; + + /** The key to get the tab title of Delta. */ + public static final String TAB_TITLE_DELA = "tabdelta"; + + /** The key to get the tab title of SnapShot. */ + public static final String TAB_TITLE_SNAPSHOT = "tabsnapshot"; + + /** The key to get the tab title of Resource. */ + public static final String TAB_TITLE_RESOUCE = "tabresouce"; + + /** The key to get the tab title of Log Collect. */ + public static final String TAB_TITLE_LOG = "tablogcollection"; + + /** Ranking Settings dialog label title. */ + public static final String RANK_LEVEL = "ranktitle"; + + /** The key to get the tab title of Log Collect. */ + public static final String MAIN_TAB_LOGCOLLECT = "maintablog"; + + /** The key to get the tab title of SnapShot. */ + public static final String MAIN_TAB_SNAPSHOT = "maintabsnapshot"; + + /** Select Log Main Title. */ + public static final String TITLE_LOG = "titellog"; + + /** LOG SELECT Button. */ + public static final String BUTTON_LOG_SELECT = "logselectbutton"; + + // SELECT DATA + /** SELECT DATA MAIN TITLE. */ + public static final String TITLE_MAIN = "titlemain"; + + /** SELECT DATA BUTTON. */ + public static final String SELECT_DATA = "selectdata"; + + /** SELECT RAGE LABEL. */ + public static final String SELECT_RANGE = "selectrange"; + + // Summary Data + /** The accordion panel title of the chart statistics. */ + public static final String TITLE_STATISTICS = "titlestatistics"; + + /** the row key. */ + public static final String TOTAL_HEAP_SIZE = "totalheapsize"; + + /** the row key. */ + public static final String NEW_HEAP = "newheapsize"; + + /** the row key. */ + public static final String OLD_HEAP = "oldheapsize"; + + /** the row key. */ + public static final String GCTIME = "gctime"; + + /** the table key. */ + public static final String TITLE_SUMMARY = "titlesummary"; + + /** the table key. */ + public static final String SNAPCOUNT = "snapcount"; + + /** the table key. */ + public static final String GCCOUNT = "gccount"; + + /** the table key. */ + public static final String LATEST_HEAP = "latestheapusage"; + + /** the table key. */ + public static final String MIN_GCTIME = "mingctime"; + + /** the table key. */ + public static final String MAX_GCTIME = "maxgctime"; + + // Delta Data + /** The accordion panel title of the chart ranking(size). */ + public static final String TITLE_SIZE_DELTE = "titledeltasize"; + + /** The accordion panel title of the chart ranking(instance). */ + public static final String TITLE_INSTANCE_DELTE = "titledeltainstance"; + + /** The accordion panel title of the chart delta(size). */ + public static final String TITLE_SIZE_AREA = "titleareachartsize"; + + /** The accordion panel title of the chart delta(instance). */ + public static final String TITLE_INSTANCE_AREA = "titleareachartinstance"; + + /** The accordion panel title of the objects list. */ + public static final String TITLE_OBJECTLIST = "titleobjectslist"; + + /** the table title of the object name. */ + public static final String OBJECTLIST_NAME = "name"; + + /** the table title of the object instances. */ + public static final String OBJECTLIST_INSTANCE = "instances"; + + /** the table title of the heap usage. */ + public static final String OBJECTLIST_SIZE = "size"; + + /** Class Filter Label title. */ + public static final String CLASS_FILTER_LABEL_TITLE = "titlefilter"; + + /** Class Filter ADD Button. */ + public static final String CLASS_FILTER_ADD = "addfilter"; + + /** Class Search Label title. */ + public static final String CLASS_SEARCH_LABEL_TITLE = "titlesearch"; + + /** Exclude Key. */ + public static final String CLASS_FILTER_EXCLUDE = "exclude"; + + /** Filter Name Key. */ + public static final String CLASS_FILTER_FILENAME = "filtername"; + + /** Sort button(instance). */ + public static final String SORT_INSTANCE = "sortinstance"; + + /** Sort button(heap usage). */ + public static final String SORT_SIZE = "sortsize"; + + // SnapShot Data + /** The accordion panel title of the SnapShot Data. */ + public static final String TITLE_SNAPSHOT = "titlesnapshot"; + + /** The accordion panel title of the chart heap usage. */ + public static final String TITLE_PIECHART = "titlepiechart"; + + /** the table key. */ + public static final String SNAPSHOTINFO_DATE = "date"; + + /** the table key. */ + public static final String SNAPSHOTINFO_ENTRYIES = "entries"; + + /** the table key. */ + public static final String SNAPSHOTINFO_HEAP = "totalheapusage"; + + /** the table key. */ + public static final String SNAPSHOTINFO_CAUSE = "sscause"; + + /** the table key. */ + public static final String SNAPSHOTINFO_GCCAUSE = "gccause"; + + /** The format of the time you draw on screen. */ + public static final String DATE_FORMAT = "yyyyMMdd HH:mm:ss"; + + /** The format of the time you draw on screen. */ + public static final String CHART_DATE_FORMAT = "MMdd HH:mm:ss.SSS"; + + // Log Data + /** The key to get the tab title of Resource. */ + public static final String TAB_RESOURCE_SUMMARY = "tabresource"; + + /** The key to get the tab title of LogDetail. */ + public static final String TAB_LOG_DETAIL = "tablogdetail"; + + /** The accordion panel title of the Resource reports. */ + public static final String TITLE_RESOURCE_REPORT = "titleresource"; + + /** The accordion panel title of the Process reports. */ + public static final String TITLE_THREAD_SUMMARY = "processreports"; + + /** The accordion panel title of the Resource reports. */ + public static final String TITLE_RESOURCE = "titleresouce"; + + /** Name javaCPU chart. */ + public static final String GRAPH_JAVA_CPU = "graphjavacpu"; + + /** Name systemCPU chart. */ + public static final String GRAPH_SYSTEM_CPU = "graphsyscpu"; + + /** Name java Memory chart. */ + public static final String GRAPH_JAVA_MEMORY = "graphjavamem"; + + /** Name threads chart. */ + public static final String GRAPH_THREADS = "graphthread"; + + /** Field name of table. */ + public static final String ITEM_CPU_AVERAGE = "cpuave"; + + /** Field name of table. */ + public static final String ITEM_CPU_PEAK = "cpupeak"; + + /** Field name of table. */ + public static final String ITEM_VSZ_AVERAGE = "vszave"; + + /** Field name of table. */ + public static final String ITEM_VSZ_PEAK = "vszpeak"; + + /** Field name of table. */ + public static final String ITEM_RSS_AVERAGE = "rssave"; + + /** Field name of table. */ + public static final String ITEM_RSS_PEAK = "rsspeak"; + + /** The name of the Log Detail Data button. */ + public static final String NEXT_BUTTON = "nextbutton"; + + /** The name of the Log Detail Data button. */ + public static final String PREV_BUTTON = "prevbutton"; + + /** The Log Detail Data Table Header Name. */ + public static final String LOG_HEAD_ITEM = "tableheaditem"; + + /** The Log Detail Data Table Header Name. */ + public static final String LOG_HEAD_DATA = "tableheaddata"; + + /** POPUPMENU-CUT key. */ + public static final String POPUP_CUT = "popupcut"; + + /** POPUPMENU-COPY key. */ + public static final String POPUP_COPY = "popupcopy"; + + /** POPUPMENU-PASTE key. */ + public static final String POPUP_PASTE = "popuppaste"; + + /** POPUPMENU-FIND key. */ + public static final String POPUP_FIND = "popupfind"; + + // Find Dialog + /** The key for obtain the title of the search dialog. */ + public static final String FIND_TITLE = "findtitle"; + + /** The key for obtain the label of the search dialog. */ + public static final String FIND_LABEL = "findlabel"; + + /** The key for obtain the name of the button of the search dialog. */ + public static final String FIND_NEXT = "findnext"; + + /** The key for obtain the name of the button of the search dialog. */ + public static final String FIND_CANCEL = "findcancel"; + + // Message + /** Start the filter. */ + public static final String BASEI01 = "base-i-01"; + + /** Complete output of the CSV. */ + public static final String BASEI02 = "base-i-02"; + + /** "%s" string can not be found in the rear. */ + public static final String BASEI03 = "base-i-03"; + + /** Failed to load heapstats.properties. Use the default values. */ + public static final String BASEW01 = "base-w-01"; + + /** Please try again after waiting some time for processing. */ + public static final String BASEW02 = "base-w-02"; + + /** Please input numeric value. */ + public static final String BASEE01 = "base-e-01"; + + /** Please input positive value. */ + public static final String BASEE02 = "base-e-02"; + + /** Please open SnapShot file. */ + public static final String BASEE03 = "base-e-03"; + + /** Please specify the period. */ + public static final String BASEE05 = "base-e-05"; + + /** Please select the time period again. */ + public static final String BASEE06 = "base-e-06"; + + /** Start and end are the same. */ + public static final String BASEE07 = "base-e-07"; + + /** Failed to load the file. */ + public static final String BASEE08 = "base-e-08"; + + /** Couldn't find library directory. (%) */ + public static final String BASEE09 = "base-e-09"; + + /** Duplicate filter name it, we canceled the loading. */ + public static final String BASEE10 = "base-e-10"; + + /** An error occurred while loading a filter definition file. (%) */ + public static final String BASEE11 = "base-e-11"; + + /** [SnapShot Data] failed to draw. */ + public static final String BASEE12 = "base-e-12"; + + /** [Delta Data] failed to draw. */ + public static final String BASEE13 = "base-e-13"; + + /** [Summary Data] failed to draw. */ + public static final String BASEE14 = "base-e-14"; + + /** Failed to output CSV. [%s] */ + public static final String BASEE15 = "base-e-15"; + + /** Error occurred during startup. Please reboot. */ + public static final String BASEE16 = "base-e-16"; + + /** Failed to write the properties file. */ + public static final String BASEE17 = "base-e-17"; + + /** Failed to open the file. */ + public static final String BASEE18 = "base-e-18"; + + /** Failed to decode the file. */ + public static final String BASEE19 = "base-e-19"; + + /** [Resource Data] failed to draw. */ + public static final String BASEE20 = "base-e-20"; + + /** Couldn't find the library. (%) */ + public static final String BASEE21 = "base-e-21"; + + /** Default Frame Width. */ + public static final int DEFAULT_FRAME_WIDTH = 800; + + /** Default Frame Height. */ + public static final int DEFAULT_FRAME_HEIGHT = 600; + + /** Default width. */ + public static final int DEFAULT_DIALOG_WIDTH = 600; + + /** Default Height. */ + public static final int DEFAULT_DIALOG_HEIGHT = 400; + + /** Replacement character. */ + public static final String REPLACEMENT_CHAR = "%s"; + + /** Analyzer window title. */ + public static final String ANALYZER_TITLE = "HeapStats Analyzer"; + + /** Border size. */ + public static final int BORDER_SIZE = 5; + + /** Thread dump file name of the agent has collected. */ + public static final String THREAD_DUNM_FILE = "threaddump.txt"; + + /** Split character to split the file path for multiple. */ + public static final String SPLIT_CHARACTER = ";"; + + /** Default Language.Default is English. */ + private static final String DEFAULT_LANGUAGE = "en"; + + /** Default Ranking Level.Default is 5. */ + private static final int DEFAULT_RANKING = 5; + + /** Rename the class path to the screen. Default is false. */ + private static final boolean DEFAULT_REPLACE = false; + + /** the HeapStatus property file name. */ + private static final String CONFIG_HEAPSTATS = "heapstats.properties"; + + /** Default Language. */ + private static String language = DEFAULT_LANGUAGE; + + /** Default Ranking Level. */ + private static int rankLevel = DEFAULT_RANKING; + + /** the current directory. */ + private static File currentDir; + + /** Rename the class path to the screen. Renaming is true. */ + private static boolean classRename = DEFAULT_REPLACE; + + /** Rename the class path to the screen. Renaming is true. */ + private static String logfiles = ""; + + /** Rename the class path to the screen. Renaming is true. */ + private static String socketend = ""; + + /** Background color of the chart. */ + private static int bgColor = 0; + + /** Multilingual Resources. */ + private static ResourceBundle resources = ResourceBundle.getBundle( + "HeapStatsResources", new Locale(language)); + + /** The properties file heapstats. */ + private static Properties prop = new Properties(); + + /** + * Don't let anyone instantiate this class. + */ + private GuiCommon() { + } + + /** + * Load the properties file. + * + * @throws Exception if the file does not exist, is a directory rather than + * a regular file, or for some other reason cannot be opened for + * reading. + */ + public static void load() throws Exception { + InputStream inputStream = null; + try { + File pp = new File(CONFIG_HEAPSTATS); + inputStream = new FileInputStream(pp); + prop.load(inputStream); + language = prop.getProperty("language"); + if (language == null + || (!language.equals(DEFAULT_LANGUAGE) && !language + .equals("ja"))) { + throw new Exception(); + } + rankLevel = Integer.decode(prop.getProperty("ranklevel")); + if (rankLevel < 1) { + throw new Exception(); + } + classRename = Boolean.parseBoolean(prop.getProperty("replace")); + if (prop.getProperty("defaultdir") != null) { + currentDir = new File(prop.getProperty("defaultdir")); + } + logfiles = prop.getProperty("logfile"); + socketend = prop.getProperty("socketend"); + bgColor = Integer.decode(prop.getProperty("bgcolor")); + } catch (Exception e) { + language = DEFAULT_LANGUAGE; + rankLevel = DEFAULT_RANKING; + classRename = DEFAULT_REPLACE; + logfiles = ""; + socketend = ""; + currentDir = null; + bgColor = 0; + + throw e; + } finally { + if (inputStream != null) { + inputStream.close(); + } + } + resources = ResourceBundle.getBundle("HeapStatsResources", new Locale( + language)); + } + + /** + * Return the Language. + * + * @return Return the Language + */ + public static String getLanguage() { + return language; + } + + /** + * Return the Ranking level. + * + * @return Return the Ranking level. + */ + public static int getRankLevel() { + return rankLevel; + } + + /** + * Sets a Ranking level. + * + * @param rank ranking + * @throws IOException if an I/O error occurs. + */ + public static void setRankLevel(final int rank) throws IOException { + OutputStream outputstream = null; + try { + outputstream = new FileOutputStream(CONFIG_HEAPSTATS); + prop.setProperty("ranklevel", Integer.toString(rank)); + prop.store(outputstream, null); + rankLevel = rank; + } finally { + if (outputstream != null) { + outputstream.close(); + } + } + } + + /** + * Returns the class path to rename. + * + * @return Returns the class path to rename. + */ + public static boolean getClassRename() { + return classRename; + } + + /** + * Return the List of log file to read. + * + * @return Return the List of log file to read + */ + public static String getLogfiles() { + return logfiles; + } + + /** + * Return the List of socket file. + * + * @return Return the List of socket file + */ + public static String getSocketend() { + return socketend; + } + + /** + * Return the Background color of the chart. + * + * @return Return the Background color of the chart + */ + public static int getBgColor() { + return bgColor; + } + + /** + * Return the resource. + * + * @return Return the resource + */ + public static ResourceBundle getResources() { + return resources; + } + + /** + * Return the current directory. + * + * @return Return the current directory + */ + public static File getCurrentDir() { + return currentDir; + } + + /** + * Sets the current directory. + * + * @param directory current directory + * @throws IOException if writing this property list to the specified output + * stream throws an IOException. + */ + public static void setCurrentDir(final File directory) throws IOException { + OutputStream outputstream = null; + try { + currentDir = directory; + outputstream = new FileOutputStream(CONFIG_HEAPSTATS); + prop.setProperty("defaultdir", directory.getAbsolutePath()); + prop.store(outputstream, null); + } finally { + if (outputstream != null) { + outputstream.close(); + } + } + } + + /** + * Brings up a dialog that displays a message using a default icon + * determined by the messageType parameter. + * + * @param component determines the Frame in which the dialog is displayed; + * if null, or if the parentComponent has no Frame, a default Frame + * is used + * @param messageId the Object to display id + * @param messageType the type of message to be displayed: ERROR_MESSAGE, + * INFORMATION_MESSAGE, WARNING_MESSAGE, QUESTION_MESSAGE, or + * PLAIN_MESSAGE + */ + public static void showMessage(final Component component, + final String messageId, final int messageType) { + try { + JOptionPane + .showMessageDialog(component, + resources.getString(messageId), ANALYZER_TITLE, + messageType); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Brings up a dialog that displays a message using a default icon + * determined by the messageType parameter. + * + * @param component determines the Frame in which the dialog is displayed; + * if null, or if the parentComponent has no Frame, a default Frame + * is used + * @param messageId the Object to display id + * @param replacement The replacement sequence of char values + * @param messageType the type of message to be displayed: ERROR_MESSAGE, + * INFORMATION_MESSAGE, WARNING_MESSAGE, QUESTION_MESSAGE, or + * PLAIN_MESSAGE + */ + public static void showMessage(final Component component, + final String messageId, final String replacement, + final int messageType) { + try { + JOptionPane.showMessageDialog( + component, + resources.getString(messageId).replace(REPLACEMENT_CHAR, + replacement), ANALYZER_TITLE, messageType); + } catch (Exception e) { + e.printStackTrace(); + } + } +}
--- a/analyzer/src/jp/co/ntt/oss/heapstats/gui/LogDetailDialog.java Mon Jun 24 11:42:50 2013 +0900 +++ b/analyzer/src/jp/co/ntt/oss/heapstats/gui/LogDetailDialog.java Mon Jun 24 18:06:21 2013 -0700 @@ -1,1194 +1,1194 @@ -/* - * LogDetailDialog.java - * Created on 2012/01/24 - * - * Copyright (C) 2011-2013 Nippon Telegraph and Telephone Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program 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 for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ -package jp.co.ntt.oss.heapstats.gui; - -import java.awt.Dimension; -import java.awt.FlowLayout; -import java.awt.Font; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.KeyEvent; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - -import javax.swing.JButton; -import javax.swing.JDialog; -import javax.swing.JLabel; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JScrollPane; -import javax.swing.JSplitPane; -import javax.swing.JTable; -import javax.swing.JTextArea; -import javax.swing.table.DefaultTableModel; -import javax.swing.table.TableColumn; -import javax.swing.text.DefaultEditorKit; - -import jp.co.ntt.oss.heapstats.container.ThreadData; - -/** - * extends {@link JDialog}<br> - * implements {@link ActionListener}<br> - * <br> - * Draw a graphical representation of system resources and java. - */ -public class LogDetailDialog extends JDialog implements - ActionListener { - /** serialVersionUID. */ - private static final long serialVersionUID = -1796436599399658541L; - - /** Number of columns in the log collection list. */ - private static final int COL_COUNT = 4; - - private static final int COL_IDX_PATH = 3; - - /** The width of the item column. */ - private static final int ITEM_WIDTH = 100; - - /** The width of the data column. */ - private static final int DATA_WIDTH = 130; - - /** The width of the browse button. */ - private static final int BROWSE_WIDTH = 35; - - /** Hexadecimal. */ - private static final int HEX_STARING = 16; - - /** Socket status:ESTABLISHED. */ - private static final int VAL_ESTABLISHED = 1; - - /** Socket status:SYN_SENT. */ - private static final int VAL_SYN_SENT = 2; - - /** Socket status:SYN_RECV. */ - private static final int VAL_SYN_RECV = 3; - - /** Socket status:FIN_WAIT1. */ - private static final int VAL_FIN_WAIT1 = 4; - - /** Socket status:FIN_WAIT2. */ - private static final int VAL_FIN_WAIT2 = 5; - - /** Socket status:TIME_WAIT. */ - private static final int VAL_TIME_WAIT = 6; - - /** Socket status:CLOSE. */ - private static final int VAL_CLOSE = 7; - - /** Socket status:CLOSE_WAIT. */ - private static final int VAL_CLOSE_WAIT = 8; - - /** Socket status:LAST_ACK. */ - private static final int VAL_LAST_ACK = 9; - - /** Socket status:LISTEN. */ - private static final int VAL_LISTEN = 10; - - /** Socket status:CLOSING. */ - private static final int VAL_CLOSING = 11; - - /** Socket endpoints header string. */ - private static final String HEAD_PROTO = "Proto "; - - /** Socket endpoints header string. */ - private static final String HEAD_RECV_Q = "Recv-Q "; - - /** Socket endpoints header string. */ - private static final String HEAD_SEND_Q = "Send-Q "; - - /** Socket endpoints header string. */ - private static final String HEAD_V4_LOCAL = "Local Address "; - - /** Socket endpoints header string. */ - private static final String HEAD_V6_LOCAL = "Local Address "; - - /** Socket endpoints header string. */ - private static final String HEAD_V4_FOREIGN = "Foreign Address "; - - /** Socket endpoints header string. */ - private static final String HEAD_V6_FOREIGN = "Foreign Address "; - - /** Socket endpoints header string. */ - private static final String HEAD_STATE = "State"; - - /** Summary header of deadlock. */ - private static final String HEAD_THREAD_CLASS = "class"; - - /** Summary header of deadlock. */ - private static final String HEAD_THREAD_METHOD = "method"; - - /** Summary header of deadlock. */ - private static final String HEAD_THREAD_THREAD = "waiter-thread"; - - /** Summary header of deadlock. */ - private static final String HEAD_THREAD_WAIT = "owner-thread"; - - /** Socket status:ESTABLISHED. */ - private static final String ESTABLISHED = "ESTABLISHED"; - - /** Socket status:SYN_SENT. */ - private static final String SYN_SENT = "SYN_SENT"; - - /** Socket status:FIN_WAIT1. */ - private static final String SYN_RECV = "SYN_RECV"; - - /** Socket status:FIN_WAIT1. */ - private static final String FIN_WAIT1 = "FIN_WAIT1"; - - /** Socket status:FIN_WAIT2. */ - private static final String FIN_WAIT2 = "FIN_WAIT2"; - - /** Socket status:TIME_WAIT. */ - private static final String TIME_WAIT = "TIME_WAIT"; - - /** Socket status:CLOSE. */ - private static final String CLOSE = "CLOSE"; - - /** Socket status:CLOSE_WAIT. */ - private static final String CLOSE_WAIT = "CLOSE_WAIT"; - - /** Socket status:LAST_ACK. */ - private static final String LAST_ACK = "LAST_ACK"; - - /** Socket status:LISTEN. */ - private static final String LISTEN = "LISTEN"; - - /** Socket status:CLOSING. */ - private static final String CLOSING = "CLOSING"; - - /** Trigger the collection log is resource exhausted. */ - private static final int TRIGGER_RESOURCE_EXHAUSTED = 1; - - /** Trigger the collection log is signal. */ - private static final int TRIGGER_SIGNAL = 2; - - /** Trigger the collection log is dead lock. */ - private static final int TRIGGER_DEADLOCK = 4; - - /** Font size of the display area is a detailed log. */ - private static final int FONT_SIZE = 15; - - /** Item name indicates the socket end point of view a detailed log. */ - private static final String SOCKET_ITEMNAME = "Socket"; - - /** Item name display shows the detailed log of deadlock. */ - private static final String DEADLOCK_ITEMNAME = "ThreadDump"; - - /** The name of the file at run-time environment information. */ - private static final String FILE_ENVINFO = "envInfo.txt"; - - /** The zip file lists failure information. */ - private List<String> zipList; - - /** Mainframe heapstats. */ - private GUIMain guimain; - - /** Main Component. */ - private JSplitPane comp; - - /** Component of the Next button. */ - private JButton nextBtn; - - /** Previous Button Component. */ - private JButton preBtn; - - /** Table model to display the details of the log. */ - private DefaultTableModel model; - - /** All information display area. */ - private JTextArea detail; - - /** Index of zip files that are currently displayed. */ - private int currentIndex; - - /** Find dialog. */ - private FindDialog findDlg; - - /** Pop-up menu. */ - private JPopupMenu popup; - - /** Find menu in the pop-up menu. */ - private JMenuItem search; - - /** Holds the type of factors that the agent was logged. */ - private int trigger; - - /** - * Creates a modeless dialog with the specified Dialog as its owner. - * - * @param owner the owner Dialog from which the dialog is displayed or null - * if this dialog has no owner - */ - public LogDetailDialog(final GUIMain owner) { - guimain = owner; - - setTitle(GuiCommon.getResources().getString(GuiCommon.TAB_TITLE_LOG)); - setSize(GuiCommon.DEFAULT_DIALOG_WIDTH, GuiCommon.DEFAULT_DIALOG_HEIGHT); - setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); - setModal(false); - - comp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, null, null); - addComponent(); - createPopupMenu(); - setLocationByPlatform(true); - - findDlg = new FindDialog(this, detail); - } - - /** - * Return the component. - * - * @return Return the Component - */ - public final JSplitPane getComp() { - return comp; - } - - /** - * Sets the dialog component. - * - * @param value the Main Component - */ - public final void setComp(final JSplitPane value) { - comp = value; - add(comp); - } - - /** - * Clear the log Detail data. - */ - public final void clear() { - model.setRowCount(0); - detail.setText(""); - nextBtn.setEnabled(false); - preBtn.setEnabled(false); - } - - /** - * Starts drawing the LogDetail Data. - * - * @param fileList The zip file lists failure information. - * @param index The index lists the zip file to decode - */ - public final void draw(final List<String> fileList, final int index) { - zipList = fileList; - currentIndex = index; - if (currentIndex > 0) { - preBtn.setEnabled(true); - } else { - preBtn.setEnabled(false); - } - if (currentIndex < fileList.size() - 1) { - nextBtn.setEnabled(true); - } else { - nextBtn.setEnabled(false); - } - - if (zipList.size() > 0) { - File zip = new File(zipList.get(index)); - int dot = zip.getName().indexOf("."); - String dirName; - if (dot > 0) { - dirName = zip.getName().substring(0, dot); - } else { - dirName = zip.getName(); - } - - File decParent = new File(zip.getParent(), dirName); - - File decdir = unzip(zip, decParent, true); - - if (decdir != null) { - if (!readEnvInfo(decdir) || !readLogFiles(decdir) - || !readSocketEndpoint(decdir) - || !readThreadDump(decdir)) { - model.setRowCount(0); - detail.setText(""); - unzip(zip, decParent, false); - readEnvInfo(decdir); - readLogFiles(decdir); - readSocketEndpoint(decdir); - readThreadDump(decdir); - } - } - } - - detail.setFont(new Font(Font.MONOSPACED, Font.PLAIN, FONT_SIZE)); - comp.revalidate(); - } - - @Override - public final void actionPerformed(final ActionEvent actionevent) { - Object eventSource = actionevent.getSource(); - - if (eventSource.equals(nextBtn)) { - model.setRowCount(0); - detail.setText(""); - draw(zipList, currentIndex + 1); - } else if (eventSource.equals(preBtn)) { - model.setRowCount(0); - detail.setText(""); - draw(zipList, currentIndex - 1); - } else if (eventSource.equals(search)) { - if (!findDlg.isAlwaysOnTop()) { - findDlg.setAlwaysOnTop(true); - } - findDlg.setVisible(true); - } - } - - /** - * Create components to draw on the screen. - */ - private void addComponent() { - String[] columnNames = new String[COL_COUNT]; - columnNames[0] = GuiCommon.getResources().getString( - GuiCommon.LOG_HEAD_ITEM); - columnNames[1] = GuiCommon.getResources().getString( - GuiCommon.LOG_HEAD_DATA); - columnNames[2] = ""; - columnNames[COL_IDX_PATH] = ""; - model = new DefaultTableModel(columnNames, 0); - - model.setRowCount(0); - - JTable itemEntries = new JTable(model); - - detail = new JTextArea(); - JScrollPane textScr = new JScrollPane(detail); - BrowseButton browse = new BrowseButton(this, itemEntries, detail); - - itemEntries.getColumnModel().getColumn(0).setPreferredWidth(ITEM_WIDTH); - itemEntries.getColumnModel().getColumn(1).setPreferredWidth(DATA_WIDTH); - TableColumn column = itemEntries.getColumnModel().getColumn(2); - column.setCellRenderer(browse); - column.setCellEditor(browse); - column.setMinWidth(BROWSE_WIDTH); - column.setMaxWidth(BROWSE_WIDTH); - - column = itemEntries.getColumnModel().getColumn(COL_IDX_PATH); - column.setMinWidth(0); - column.setMaxWidth(0); - - JScrollPane itemScr = new JScrollPane(itemEntries); - itemScr.setPreferredSize(new Dimension(ITEM_WIDTH + DATA_WIDTH - + BROWSE_WIDTH, itemScr.getHeight())); - - preBtn = new JButton(GuiCommon.getResources().getString( - GuiCommon.PREV_BUTTON)); - preBtn.setEnabled(false); - preBtn.addActionListener(this); - nextBtn = new JButton(GuiCommon.getResources().getString( - GuiCommon.NEXT_BUTTON)); - nextBtn.setEnabled(false); - nextBtn.addActionListener(this); - - JPanel nextPanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); - nextPanel.add(preBtn); - nextPanel.add(new JLabel(" ")); - nextPanel.add(nextBtn); - JSplitPane itemSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT, - nextPanel, itemScr); - itemSplit.setDividerSize(0); - - comp.setLeftComponent(itemSplit); - comp.setRightComponent(textScr); - comp.setOneTouchExpandable(true); - } - - /** - * Creates the popup menu. - */ - private void createPopupMenu() { - popup = new JPopupMenu(); - - JMenuItem cut = new JMenuItem(GuiCommon.getResources().getString( - GuiCommon.POPUP_CUT), KeyEvent.VK_T); - cut.addActionListener(new DefaultEditorKit.CutAction()); - popup.add(cut); - - JMenuItem copy = new JMenuItem(GuiCommon.getResources().getString( - GuiCommon.POPUP_COPY), KeyEvent.VK_C); - copy.addActionListener(new DefaultEditorKit.CopyAction()); - popup.add(copy); - - JMenuItem paste = new JMenuItem(GuiCommon.getResources().getString( - GuiCommon.POPUP_PASTE), KeyEvent.VK_P); - paste.addActionListener(new DefaultEditorKit.PasteAction()); - popup.add(paste); - - popup.addSeparator(); - - search = new JMenuItem(GuiCommon.getResources().getString( - GuiCommon.POPUP_FIND), KeyEvent.VK_F); - search.addActionListener(this); - popup.add(search); - - detail.setComponentPopupMenu(popup); - } - - /** - * Unzip the zip archive. - * - * @param file a zip archive - * @param parentDir The parent directory unzipped - * @param first Unzip the first flag true:first false:Second - * @return Return the unzipped directory - */ - private File unzip(final File file, final File parentDir, - final boolean first) { - try { - ZipFile zipFile = new ZipFile(file); - File decodeDir = parentDir; - Enumeration<? extends ZipEntry> entries = zipFile.entries(); - while (entries.hasMoreElements()) { - ZipEntry entry = entries.nextElement(); - File entryFile = new File(parentDir, entry.getName()); - if (entry.isDirectory()) { - decodeDir = entryFile; - if (!entryFile.exists()) { - entryFile.mkdirs(); - } - continue; - } - - if (!parentDir.exists()) { - decodeDir.mkdirs(); - } - - if (entryFile.exists()) { - continue; - } - - BufferedInputStream inBuff = new BufferedInputStream( - zipFile.getInputStream(entry)); - BufferedOutputStream outBuff = new BufferedOutputStream( - new FileOutputStream(entryFile)); - - int buffSize = inBuff.available(); - while (buffSize > 0) { - byte[] buff = new byte[buffSize]; - inBuff.read(buff); - outBuff.write(buff); - buffSize = inBuff.available(); - } - - inBuff.close(); - outBuff.close(); - } - - zipFile.close(); - - Object[] row = new Object[COL_COUNT]; - row[0] = "FileName"; - row[1] = file.getName(); - model.addRow(row); - - return decodeDir; - } catch (Throwable e) { - GuiCommon.showMessage(guimain, GuiCommon.BASEE19, file.getName(), - JOptionPane.ERROR_MESSAGE); - e.printStackTrace(); - } - return null; - } - - /** - * Reads envInfo.txt, to set a table. - * - * @param decDir Unzipped directory - * @return Return the result reads - */ - private boolean readEnvInfo(final File decDir) { - BufferedReader read = null; - try { - File file = new File(decDir, FILE_ENVINFO); - if (!file.exists()) { - return false; - } - read = new BufferedReader(new FileReader(file)); - - String line = read.readLine(); - int i = 0; - while (line != null) { - String[] row = new String[2]; - String[] tmp = line.split("="); - - row[0] = tmp[0]; - switch (i) { - case 0: - // Collection date - SimpleDateFormat sdf = new SimpleDateFormat( - GuiCommon.DATE_FORMAT); - row[1] = sdf.format(Long.parseLong(tmp[1])); - break; - case 1: - // Log Trigger - if (tmp[1].equals("1")) { - row[1] = "ResourceExhausted"; - trigger = TRIGGER_RESOURCE_EXHAUSTED; - } else if (tmp[1].equals("2")) { - row[1] = "Signal"; - trigger = TRIGGER_SIGNAL; - } else if (tmp[1].equals("4")) { - row[1] = "Deadlock"; - trigger = TRIGGER_DEADLOCK; - } else { - row[1] = "N/A"; - } - break; - default: - if (tmp.length > 1) { - StringBuilder sb = new StringBuilder(); - for (int n = 1; n < tmp.length; n++) { - sb.append(tmp[n]); - sb.append("="); - } - row[1] = sb.substring(0, sb.length() - 1); - } else { - row[1] = "N/A"; - } - break; - } - - model.addRow(row); - line = read.readLine(); - i++; - } - return true; - } catch (Throwable e) { - GuiCommon.showMessage(guimain, GuiCommon.BASEE08, FILE_ENVINFO, - JOptionPane.ERROR_MESSAGE); - clear(); - e.printStackTrace(); - } finally { - try { - if (read != null) { - read.close(); - } - } catch (IOException e) { - GuiCommon.showMessage(guimain, GuiCommon.BASEE08, FILE_ENVINFO, - JOptionPane.ERROR_MESSAGE); - clear(); - e.printStackTrace(); - } - } - return false; - } - - /** - * Read the log file that is set in the properties file. - * - * @param decDir Unzipped directory - * @return Return the result reads - */ - private boolean readLogFiles(final File decDir) { - BufferedReader read = null; - boolean ret = true; - try { - if (GuiCommon.getLogfiles() == null) { - return ret; - } - - for (String view : GuiCommon.getLogfiles().split(",")) { - if (view.length() == 0) { - ret = false; - continue; - } - File file = new File(decDir, view); - - Object[] row = new Object[COL_COUNT]; - row[0] = file.getName(); - if (!file.exists()) { - row[1] = "N/A"; - model.addRow(row); - ret = false; - continue; - } - read = new BufferedReader(new FileReader(file)); - - String line = read.readLine(); - StringBuilder sb = new StringBuilder(); - sb.append(line); - line = read.readLine(); - if (line != null) { - sb.append("..."); - } - - row[1] = sb.toString(); - row[COL_IDX_PATH] = file.getAbsolutePath(); - - model.addRow(row); - - read.close(); - } - return ret; - } catch (Throwable e) { - GuiCommon.showMessage(guimain, GuiCommon.BASEE08, - GuiCommon.getLogfiles(), JOptionPane.ERROR_MESSAGE); - ret = false; - clear(); - } finally { - try { - if (read != null) { - read.close(); - } - } catch (IOException e) { - GuiCommon.showMessage(guimain, GuiCommon.BASEE08, - GuiCommon.getLogfiles(), JOptionPane.ERROR_MESSAGE); - ret = false; - e.printStackTrace(); - } - } - - return ret; - } - - /** - * Read the socket file that is set in the properties file. - * - * @param decDir Unzipped directory - * @return Return the result reads - */ - private boolean readSocketEndpoint(final File decDir) { - BufferedReader read = null; - BufferedWriter write = null; - boolean ret = false; - - try { - File sockFile = new File(decDir, SOCKET_ITEMNAME); - Object[] row = new Object[COL_COUNT]; - row[0] = SOCKET_ITEMNAME; - - if (GuiCommon.getSocketend() == null) { - return !ret; - } - - for (String name : GuiCommon.getSocketend().split(",")) { - File file = new File(decDir, name); - if (!file.exists() || name.length() == 0) { - continue; - } - - if (write == null) { - write = new BufferedWriter(new FileWriter(sockFile)); - } - - read = new BufferedReader(new FileReader(file)); - read.readLine(); - - if (!file.getName().endsWith("6")) { - // IPv4 - writeSocket(write, read, file.getName(), true); - } else { - // IPv6 - writeSocket(write, read, file.getName(), false); - } - - read.close(); - ret = true; - } - if (write != null) { - write.flush(); - } - - if (ret) { - row[1] = HEAD_PROTO + "..."; - row[COL_IDX_PATH] = sockFile.getAbsolutePath(); - model.addRow(row); - } - - return ret; - } catch (Throwable e) { - GuiCommon.showMessage(guimain, GuiCommon.BASEE08, - GuiCommon.getSocketend(), JOptionPane.ERROR_MESSAGE); - ret = false; - e.printStackTrace(); - } finally { - try { - if (read != null) { - read.close(); - } - if (write != null) { - write.close(); - } - } catch (IOException e) { - GuiCommon.showMessage(guimain, GuiCommon.BASEE08, - GuiCommon.getSocketend(), JOptionPane.ERROR_MESSAGE); - ret = false; - clear(); - e.printStackTrace(); - } - } - return ret; - } - - /** - * Extracts information from files deadlock the thread dump. - * - * @param decDir The directory that contains the thread dump file - * @return Return the result of extraction - */ - private boolean readThreadDump(final File decDir) { - boolean ret = true; - - if (trigger != TRIGGER_DEADLOCK) { - return ret; - } - - Object[] row = new Object[COL_COUNT]; - row[0] = DEADLOCK_ITEMNAME; - - File dumpFile = new File(decDir, GuiCommon.THREAD_DUNM_FILE); - File lockFile = new File(decDir, DEADLOCK_ITEMNAME); - - if (!dumpFile.exists()) { - return ret; - } - - row[1] = "[Summary] ..."; - row[COL_IDX_PATH] = lockFile.getAbsolutePath() - + GuiCommon.SPLIT_CHARACTER + dumpFile.getAbsolutePath(); - - if (lockFile.exists()) { - model.addRow(row); - return ret; - } - - BufferedReader read = null; - BufferedWriter write = null; - try { - read = new BufferedReader(new FileReader(dumpFile)); - String line = read.readLine(); - - boolean isJvmti = false; - ThreadData thread = null; - Map<String, ThreadData> tmpMap = new HashMap<String, ThreadData>(); - - while (line != null) { - // Name of its own thread - int classIndex = line.indexOf("\""); - if (classIndex != -1) { - thread = new ThreadData(); - thread.setThreadName(line.substring(classIndex + 1, - line.indexOf("\"", classIndex + 1))); - } - - // Thread state - if (thread != null - && line.indexOf("java.lang.Thread.State") != -1) { - String[] split = line.trim().split(" "); - if (!split[1].trim().equals("BLOCKED")) { - thread = null; - } - } - - // Class name Method name - if (thread != null && (line.trim().indexOf("at") == 0)) { - String[] split = line.trim().split(" "); - String classMethod = split[1].split("\\(")[0]; - thread.setMethodName(classMethod.substring(classMethod - .lastIndexOf(".") + 1)); - thread.setClassName(classMethod.substring(0, - classMethod.lastIndexOf("."))); - } - - // wait Address or name thread - if (thread != null && line.indexOf("- waiting to lock") != -1) { - if (isJvmti || line.indexOf("owner:") != -1) { - // jvmti - isJvmti = true; - thread.setWaitThread(line.substring( - line.indexOf(":") + 1, line.indexOf(">"))); - } else { - // socket - thread.setWaitLock(line.substring( - line.indexOf("<") + 1, line.indexOf(">"))); - } - } - // lockObject address or threadName - if (thread != null && line.indexOf("- locked") != -1) { - if (isJvmti) { - // jvmti sets the thread name - thread.setLockThread(thread.getThreadName()); - } else { - // socket address - thread.setLockThread(line.substring( - line.indexOf("<") + 1, line.indexOf(">"))); - } - tmpMap.put(thread.getLockThread(), thread); - thread = null; - } - - if (thread != null - && line.indexOf("Found one Java-level deadlock") != -1) { - break; - } - line = read.readLine(); - } - - write = new BufferedWriter(new FileWriter(lockFile)); - - if (!tmpMap.isEmpty()) { - writeThreadDump(tmpMap, write, isJvmti); - - model.addRow(row); - } - } catch (IOException e) { - GuiCommon.showMessage(guimain, GuiCommon.BASEE08, - dumpFile.getName(), JOptionPane.ERROR_MESSAGE); - ret = false; - e.printStackTrace(); - } catch (Throwable e) { - GuiCommon.showMessage(guimain, GuiCommon.BASEE08, - dumpFile.getName(), JOptionPane.ERROR_MESSAGE); - ret = false; - e.printStackTrace(); - } finally { - try { - if (read != null) { - read.close(); - } - if (write != null) { - write.close(); - } - } catch (IOException e) { - GuiCommon.showMessage(guimain, GuiCommon.BASEE08, - dumpFile.getName(), JOptionPane.ERROR_MESSAGE); - ret = false; - clear(); - e.printStackTrace(); - } - } - - return ret; - } - - /** - * Create a file that shows the status of each protocol sockets. - * - * @param write The socket file buffer for writing - * @param read Socket endpoints file(tcp,udp,tcp6,udp6) - * @param name Protocol name - * @param v4 IP version flag true:IPv4, false:IPv6 - * @throws IOException If an I/O error occurs - */ - private void writeSocket(final BufferedWriter write, - final BufferedReader read, final String name, final boolean v4) - throws IOException { - write.write(HEAD_PROTO); - write.write(HEAD_RECV_Q); - write.write(HEAD_SEND_Q); - if (v4) { - write.write(HEAD_V4_LOCAL); - write.write(HEAD_V4_FOREIGN); - } else { - write.write(HEAD_V6_LOCAL); - write.write(HEAD_V6_FOREIGN); - } - write.write(HEAD_STATE); - - write.newLine(); - String line = read.readLine(); - while (line != null) { - write.write(name); - writeBlank(write, HEAD_PROTO.length(), name.length()); - - String[] data = line.trim().split(" "); - - // Recv_Q - String[] tmp = data[4].split(":"); - String queue = Integer.toHexString(Integer.parseInt(tmp[1], - HEX_STARING)); - write.write(queue); - writeBlank(write, HEAD_RECV_Q.length(), queue.length()); - - // Send_Q - queue = Integer.toHexString(Integer.parseInt(tmp[0], HEX_STARING)); - write.write(queue); - writeBlank(write, HEAD_SEND_Q.length(), queue.length()); - - // Local Address - tmp = data[1].split(":"); - StringBuilder buf = new StringBuilder(); - if (v4) { - buf.append(hexstringToIPv4(tmp[0])); - } else { - buf.append(hexstringToIPv6(tmp[0])); - } - buf.append(":"); - buf.append(Integer.parseInt(tmp[1], HEX_STARING)); - write.write(buf.toString()); - if (v4) { - writeBlank(write, HEAD_V4_LOCAL.length(), buf.length()); - } else { - writeBlank(write, HEAD_V6_LOCAL.length(), buf.length()); - } - - // Foreign Address - tmp = data[2].split(":"); - buf.setLength(0); - if (v4) { - buf.append(hexstringToIPv4(tmp[0])); - } else { - buf.append(hexstringToIPv6(tmp[0])); - } - buf.append(":"); - buf.append(Integer.parseInt(tmp[1], HEX_STARING)); - write.write(buf.toString()); - if (v4) { - writeBlank(write, HEAD_V4_FOREIGN.length(), buf.length()); - } else { - writeBlank(write, HEAD_V6_FOREIGN.length(), buf.length()); - } - - // connection state - writeState(write, Integer.parseInt(data[3], HEX_STARING)); - - write.newLine(); - - line = read.readLine(); - } - write.newLine(); - } - - /** - * Output a summary of the deadlock. - * - * @param threadMap Information of the thread that caused the deadlock - * @param write The thread dump file buffer for writing - * @param isJvmti If true, the output type of the thread dump file has been - * using the jvmti - * @throws IOException If an I/O error occurs - */ - private void writeThreadDump(final Map<String, ThreadData> threadMap, - final BufferedWriter write, final boolean isJvmti) - throws IOException { - - int classLength = HEAD_THREAD_CLASS.length() + 2; - int methodLength = HEAD_THREAD_METHOD.length() + 2; - int threadLength = HEAD_THREAD_THREAD.length() + 2; - for (Map.Entry<String, ThreadData> entry : threadMap.entrySet()) { - int tmp = entry.getValue().getClassName().length(); - if (classLength < tmp) { - classLength = tmp + 2; - } - tmp = entry.getValue().getMethodName().length(); - if (methodLength < tmp) { - methodLength = tmp + 2; - } - tmp = entry.getValue().getThreadName().length(); - if (threadLength < tmp) { - threadLength = tmp + 2; - } - } - - write.write("[Summary]"); - write.newLine(); - - write.write(HEAD_THREAD_CLASS); - writeBlank(write, classLength, HEAD_THREAD_CLASS.length()); - write.write(HEAD_THREAD_METHOD); - writeBlank(write, methodLength, HEAD_THREAD_METHOD.length()); - write.write(HEAD_THREAD_THREAD); - writeBlank(write, threadLength, HEAD_THREAD_THREAD.length()); - write.write(HEAD_THREAD_WAIT); - write.newLine(); - - for (Map.Entry<String, ThreadData> entry : threadMap.entrySet()) { - // class Name - write.write(entry.getValue().getClassName()); - writeBlank(write, classLength, entry.getValue().getClassName() - .length()); - - // method Name - write.write(entry.getValue().getMethodName()); - writeBlank(write, methodLength, entry.getValue().getMethodName() - .length()); - - // thread - write.write(entry.getValue().getThreadName()); - writeBlank(write, threadLength, entry.getValue().getThreadName() - .length()); - - // wait-thread - if (isJvmti) { - write.write(entry.getValue().getWaitThread()); - } else { - write.write(threadMap.get(entry.getValue().getWaitLock()) - .getThreadName()); - } - write.newLine(); - } - - write.newLine(); - write.write("[Detail]"); - write.newLine(); - } - - /** - * Setting up a blank to fill the specified size. - * - * @param write The socket file buffer for writing - * @param length Header length of a single item - * @param strLen The length of a character string to write in - * @throws IOException If an I/O error occurs - */ - private void writeBlank(final BufferedWriter write, final int length, - final int strLen) throws IOException { - for (int i = 0; i < (length - strLen); i++) { - write.write(" "); - } - } - - /** - * That converts decimal IPv4 of the IPv4 in hex. - * - * @param data IPv4 before conversion - * @return The IPv4 of the converted - */ - private String hexstringToIPv4(final String data) { - - StringBuilder ipv4 = new StringBuilder(); - try { - ipv4.append(Integer.parseInt(data.substring(6, 8), HEX_STARING)); - ipv4.append("."); - ipv4.append(Integer.parseInt(data.substring(4, 6), HEX_STARING)); - ipv4.append("."); - ipv4.append(Integer.parseInt(data.substring(2, 4), HEX_STARING)); - ipv4.append("."); - ipv4.append(Integer.parseInt(data.substring(0, 2), HEX_STARING)); - } catch (NumberFormatException e) { - ipv4.setLength(0); - } - - return ipv4.toString(); - } - - /** - * That converts decimal IPv6 of the IPv6 in hex. - * - * @param data IPv6 before conversion - * @return The IPv6 of the converted - */ - private String hexstringToIPv6(final String data) { - StringBuilder ipv6 = new StringBuilder(); - - String hex = data.substring(6, 8) + data.substring(4, 6); - ipv6.append(Integer.toHexString(Integer.parseInt(hex, HEX_STARING))); - ipv6.append(":"); - - hex = data.substring(2, 4) + data.substring(0, 2); - ipv6.append(Integer.toHexString(Integer.parseInt(hex, HEX_STARING))); - ipv6.append(":"); - - hex = data.substring(14, 16) + data.substring(12, 14); - ipv6.append(Integer.toHexString(Integer.parseInt(hex, HEX_STARING))); - ipv6.append(":"); - - hex = data.substring(10, 12) + data.substring(8, 10); - ipv6.append(Integer.toHexString(Integer.parseInt(hex, HEX_STARING))); - ipv6.append(":"); - - hex = data.substring(22, 24) + data.substring(20, 22); - ipv6.append(Integer.toHexString(Integer.parseInt(hex, HEX_STARING))); - ipv6.append(":"); - - hex = data.substring(18, 20) + data.substring(16, 18); - ipv6.append(Integer.toHexString(Integer.parseInt(hex, HEX_STARING))); - ipv6.append(":"); - - hex = data.substring(30, 32) + data.substring(28, 30); - ipv6.append(Integer.toHexString(Integer.parseInt(hex, HEX_STARING))); - ipv6.append(":"); - - hex = data.substring(26, 28) + data.substring(24, 26); - ipv6.append(Integer.toHexString(Integer.parseInt(hex, HEX_STARING))); - - return ipv6.toString(); - } - - /** - * Convert a numeric string from Socket status. - * - * @param write Socket information text file - * @param state Socket status. - * @throws IOException If an I/O error occurs - */ - private void writeState(final BufferedWriter write, final int state) - throws IOException { - switch (state) { - case VAL_ESTABLISHED: - write.write(ESTABLISHED); - break; - case VAL_SYN_SENT: - write.write(SYN_SENT); - break; - case VAL_SYN_RECV: - write.write(SYN_RECV); - break; - case VAL_FIN_WAIT1: - write.write(FIN_WAIT1); - break; - case VAL_FIN_WAIT2: - write.write(FIN_WAIT2); - break; - case VAL_TIME_WAIT: - write.write(TIME_WAIT); - break; - case VAL_CLOSE: - write.write(CLOSE); - break; - case VAL_CLOSE_WAIT: - write.write(CLOSE_WAIT); - break; - case VAL_LAST_ACK: - write.write(LAST_ACK); - break; - case VAL_LISTEN: - write.write(LISTEN); - break; - case VAL_CLOSING: - write.write(CLOSING); - break; - default: - write.write("-"); - break; - } - } -} +/* + * LogDetailDialog.java + * Created on 2012/01/24 + * + * Copyright (C) 2011-2013 Nippon Telegraph and Telephone Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ +package jp.co.ntt.oss.heapstats.gui; + +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; +import javax.swing.JTable; +import javax.swing.JTextArea; +import javax.swing.table.DefaultTableModel; +import javax.swing.table.TableColumn; +import javax.swing.text.DefaultEditorKit; + +import jp.co.ntt.oss.heapstats.container.ThreadData; + +/** + * extends {@link JDialog}<br> + * implements {@link ActionListener}<br> + * <br> + * Draw a graphical representation of system resources and java. + */ +public class LogDetailDialog extends JDialog implements + ActionListener { + /** serialVersionUID. */ + private static final long serialVersionUID = -1796436599399658541L; + + /** Number of columns in the log collection list. */ + private static final int COL_COUNT = 4; + + private static final int COL_IDX_PATH = 3; + + /** The width of the item column. */ + private static final int ITEM_WIDTH = 100; + + /** The width of the data column. */ + private static final int DATA_WIDTH = 130; + + /** The width of the browse button. */ + private static final int BROWSE_WIDTH = 35; + + /** Hexadecimal. */ + private static final int HEX_STARING = 16; + + /** Socket status:ESTABLISHED. */ + private static final int VAL_ESTABLISHED = 1; + + /** Socket status:SYN_SENT. */ + private static final int VAL_SYN_SENT = 2; + + /** Socket status:SYN_RECV. */ + private static final int VAL_SYN_RECV = 3; + + /** Socket status:FIN_WAIT1. */ + private static final int VAL_FIN_WAIT1 = 4; + + /** Socket status:FIN_WAIT2. */ + private static final int VAL_FIN_WAIT2 = 5; + + /** Socket status:TIME_WAIT. */ + private static final int VAL_TIME_WAIT = 6; + + /** Socket status:CLOSE. */ + private static final int VAL_CLOSE = 7; + + /** Socket status:CLOSE_WAIT. */ + private static final int VAL_CLOSE_WAIT = 8; + + /** Socket status:LAST_ACK. */ + private static final int VAL_LAST_ACK = 9; + + /** Socket status:LISTEN. */ + private static final int VAL_LISTEN = 10; + + /** Socket status:CLOSING. */ + private static final int VAL_CLOSING = 11; + + /** Socket endpoints header string. */ + private static final String HEAD_PROTO = "Proto "; + + /** Socket endpoints header string. */ + private static final String HEAD_RECV_Q = "Recv-Q "; + + /** Socket endpoints header string. */ + private static final String HEAD_SEND_Q = "Send-Q "; + + /** Socket endpoints header string. */ + private static final String HEAD_V4_LOCAL = "Local Address "; + + /** Socket endpoints header string. */ + private static final String HEAD_V6_LOCAL = "Local Address "; + + /** Socket endpoints header string. */ + private static final String HEAD_V4_FOREIGN = "Foreign Address "; + + /** Socket endpoints header string. */ + private static final String HEAD_V6_FOREIGN = "Foreign Address "; + + /** Socket endpoints header string. */ + private static final String HEAD_STATE = "State"; + + /** Summary header of deadlock. */ + private static final String HEAD_THREAD_CLASS = "class"; + + /** Summary header of deadlock. */ + private static final String HEAD_THREAD_METHOD = "method"; + + /** Summary header of deadlock. */ + private static final String HEAD_THREAD_THREAD = "waiter-thread"; + + /** Summary header of deadlock. */ + private static final String HEAD_THREAD_WAIT = "owner-thread"; + + /** Socket status:ESTABLISHED. */ + private static final String ESTABLISHED = "ESTABLISHED"; + + /** Socket status:SYN_SENT. */ + private static final String SYN_SENT = "SYN_SENT"; + + /** Socket status:FIN_WAIT1. */ + private static final String SYN_RECV = "SYN_RECV"; + + /** Socket status:FIN_WAIT1. */ + private static final String FIN_WAIT1 = "FIN_WAIT1"; + + /** Socket status:FIN_WAIT2. */ + private static final String FIN_WAIT2 = "FIN_WAIT2"; + + /** Socket status:TIME_WAIT. */ + private static final String TIME_WAIT = "TIME_WAIT"; + + /** Socket status:CLOSE. */ + private static final String CLOSE = "CLOSE"; + + /** Socket status:CLOSE_WAIT. */ + private static final String CLOSE_WAIT = "CLOSE_WAIT"; + + /** Socket status:LAST_ACK. */ + private static final String LAST_ACK = "LAST_ACK"; + + /** Socket status:LISTEN. */ + private static final String LISTEN = "LISTEN"; + + /** Socket status:CLOSING. */ + private static final String CLOSING = "CLOSING"; + + /** Trigger the collection log is resource exhausted. */ + private static final int TRIGGER_RESOURCE_EXHAUSTED = 1; + + /** Trigger the collection log is signal. */ + private static final int TRIGGER_SIGNAL = 2; + + /** Trigger the collection log is dead lock. */ + private static final int TRIGGER_DEADLOCK = 4; + + /** Font size of the display area is a detailed log. */ + private static final int FONT_SIZE = 15; + + /** Item name indicates the socket end point of view a detailed log. */ + private static final String SOCKET_ITEMNAME = "Socket"; + + /** Item name display shows the detailed log of deadlock. */ + private static final String DEADLOCK_ITEMNAME = "ThreadDump"; + + /** The name of the file at run-time environment information. */ + private static final String FILE_ENVINFO = "envInfo.txt"; + + /** The zip file lists failure information. */ + private List<String> zipList; + + /** Mainframe heapstats. */ + private GUIMain guimain; + + /** Main Component. */ + private JSplitPane comp; + + /** Component of the Next button. */ + private JButton nextBtn; + + /** Previous Button Component. */ + private JButton preBtn; + + /** Table model to display the details of the log. */ + private DefaultTableModel model; + + /** All information display area. */ + private JTextArea detail; + + /** Index of zip files that are currently displayed. */ + private int currentIndex; + + /** Find dialog. */ + private FindDialog findDlg; + + /** Pop-up menu. */ + private JPopupMenu popup; + + /** Find menu in the pop-up menu. */ + private JMenuItem search; + + /** Holds the type of factors that the agent was logged. */ + private int trigger; + + /** + * Creates a modeless dialog with the specified Dialog as its owner. + * + * @param owner the owner Dialog from which the dialog is displayed or null + * if this dialog has no owner + */ + public LogDetailDialog(final GUIMain owner) { + guimain = owner; + + setTitle(GuiCommon.getResources().getString(GuiCommon.TAB_TITLE_LOG)); + setSize(GuiCommon.DEFAULT_DIALOG_WIDTH, GuiCommon.DEFAULT_DIALOG_HEIGHT); + setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); + setModal(false); + + comp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, null, null); + addComponent(); + createPopupMenu(); + setLocationByPlatform(true); + + findDlg = new FindDialog(this, detail); + } + + /** + * Return the component. + * + * @return Return the Component + */ + public final JSplitPane getComp() { + return comp; + } + + /** + * Sets the dialog component. + * + * @param value the Main Component + */ + public final void setComp(final JSplitPane value) { + comp = value; + add(comp); + } + + /** + * Clear the log Detail data. + */ + public final void clear() { + model.setRowCount(0); + detail.setText(""); + nextBtn.setEnabled(false); + preBtn.setEnabled(false); + } + + /** + * Starts drawing the LogDetail Data. + * + * @param fileList The zip file lists failure information. + * @param index The index lists the zip file to decode + */ + public final void draw(final List<String> fileList, final int index) { + zipList = fileList; + currentIndex = index; + if (currentIndex > 0) { + preBtn.setEnabled(true); + } else { + preBtn.setEnabled(false); + } + if (currentIndex < fileList.size() - 1) { + nextBtn.setEnabled(true); + } else { + nextBtn.setEnabled(false); + } + + if (zipList.size() > 0) { + File zip = new File(zipList.get(index)); + int dot = zip.getName().indexOf("."); + String dirName; + if (dot > 0) { + dirName = zip.getName().substring(0, dot); + } else { + dirName = zip.getName(); + } + + File decParent = new File(zip.getParent(), dirName); + + File decdir = unzip(zip, decParent, true); + + if (decdir != null) { + if (!readEnvInfo(decdir) || !readLogFiles(decdir) + || !readSocketEndpoint(decdir) + || !readThreadDump(decdir)) { + model.setRowCount(0); + detail.setText(""); + unzip(zip, decParent, false); + readEnvInfo(decdir); + readLogFiles(decdir); + readSocketEndpoint(decdir); + readThreadDump(decdir); + } + } + } + + detail.setFont(new Font(Font.MONOSPACED, Font.PLAIN, FONT_SIZE)); + comp.revalidate(); + } + + @Override + public final void actionPerformed(final ActionEvent actionevent) { + Object eventSource = actionevent.getSource(); + + if (eventSource.equals(nextBtn)) { + model.setRowCount(0); + detail.setText(""); + draw(zipList, currentIndex + 1); + } else if (eventSource.equals(preBtn)) { + model.setRowCount(0); + detail.setText(""); + draw(zipList, currentIndex - 1); + } else if (eventSource.equals(search)) { + if (!findDlg.isAlwaysOnTop()) { + findDlg.setAlwaysOnTop(true); + } + findDlg.setVisible(true); + } + } + + /** + * Create components to draw on the screen. + */ + private void addComponent() { + String[] columnNames = new String[COL_COUNT]; + columnNames[0] = GuiCommon.getResources().getString( + GuiCommon.LOG_HEAD_ITEM); + columnNames[1] = GuiCommon.getResources().getString( + GuiCommon.LOG_HEAD_DATA); + columnNames[2] = ""; + columnNames[COL_IDX_PATH] = ""; + model = new DefaultTableModel(columnNames, 0); + + model.setRowCount(0); + + JTable itemEntries = new JTable(model); + + detail = new JTextArea(); + JScrollPane textScr = new JScrollPane(detail); + BrowseButton browse = new BrowseButton(this, itemEntries, detail); + + itemEntries.getColumnModel().getColumn(0).setPreferredWidth(ITEM_WIDTH); + itemEntries.getColumnModel().getColumn(1).setPreferredWidth(DATA_WIDTH); + TableColumn column = itemEntries.getColumnModel().getColumn(2); + column.setCellRenderer(browse); + column.setCellEditor(browse); + column.setMinWidth(BROWSE_WIDTH); + column.setMaxWidth(BROWSE_WIDTH); + + column = itemEntries.getColumnModel().getColumn(COL_IDX_PATH); + column.setMinWidth(0); + column.setMaxWidth(0); + + JScrollPane itemScr = new JScrollPane(itemEntries); + itemScr.setPreferredSize(new Dimension(ITEM_WIDTH + DATA_WIDTH + + BROWSE_WIDTH, itemScr.getHeight())); + + preBtn = new JButton(GuiCommon.getResources().getString( + GuiCommon.PREV_BUTTON)); + preBtn.setEnabled(false); + preBtn.addActionListener(this); + nextBtn = new JButton(GuiCommon.getResources().getString( + GuiCommon.NEXT_BUTTON)); + nextBtn.setEnabled(false); + nextBtn.addActionListener(this); + + JPanel nextPanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); + nextPanel.add(preBtn); + nextPanel.add(new JLabel(" ")); + nextPanel.add(nextBtn); + JSplitPane itemSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT, + nextPanel, itemScr); + itemSplit.setDividerSize(0); + + comp.setLeftComponent(itemSplit); + comp.setRightComponent(textScr); + comp.setOneTouchExpandable(true); + } + + /** + * Creates the popup menu. + */ + private void createPopupMenu() { + popup = new JPopupMenu(); + + JMenuItem cut = new JMenuItem(GuiCommon.getResources().getString( + GuiCommon.POPUP_CUT), KeyEvent.VK_T); + cut.addActionListener(new DefaultEditorKit.CutAction()); + popup.add(cut); + + JMenuItem copy = new JMenuItem(GuiCommon.getResources().getString( + GuiCommon.POPUP_COPY), KeyEvent.VK_C); + copy.addActionListener(new DefaultEditorKit.CopyAction()); + popup.add(copy); + + JMenuItem paste = new JMenuItem(GuiCommon.getResources().getString( + GuiCommon.POPUP_PASTE), KeyEvent.VK_P); + paste.addActionListener(new DefaultEditorKit.PasteAction()); + popup.add(paste); + + popup.addSeparator(); + + search = new JMenuItem(GuiCommon.getResources().getString( + GuiCommon.POPUP_FIND), KeyEvent.VK_F); + search.addActionListener(this); + popup.add(search); + + detail.setComponentPopupMenu(popup); + } + + /** + * Unzip the zip archive. + * + * @param file a zip archive + * @param parentDir The parent directory unzipped + * @param first Unzip the first flag true:first false:Second + * @return Return the unzipped directory + */ + private File unzip(final File file, final File parentDir, + final boolean first) { + try { + ZipFile zipFile = new ZipFile(file); + File decodeDir = parentDir; + Enumeration<? extends ZipEntry> entries = zipFile.entries(); + while (entries.hasMoreElements()) { + ZipEntry entry = entries.nextElement(); + File entryFile = new File(parentDir, entry.getName()); + if (entry.isDirectory()) { + decodeDir = entryFile; + if (!entryFile.exists()) { + entryFile.mkdirs(); + } + continue; + } + + if (!parentDir.exists()) { + decodeDir.mkdirs(); + } + + if (entryFile.exists()) { + continue; + } + + BufferedInputStream inBuff = new BufferedInputStream( + zipFile.getInputStream(entry)); + BufferedOutputStream outBuff = new BufferedOutputStream( + new FileOutputStream(entryFile)); + + int buffSize = inBuff.available(); + while (buffSize > 0) { + byte[] buff = new byte[buffSize]; + inBuff.read(buff); + outBuff.write(buff); + buffSize = inBuff.available(); + } + + inBuff.close(); + outBuff.close(); + } + + zipFile.close(); + + Object[] row = new Object[COL_COUNT]; + row[0] = "FileName"; + row[1] = file.getName(); + model.addRow(row); + + return decodeDir; + } catch (Throwable e) { + GuiCommon.showMessage(guimain, GuiCommon.BASEE19, file.getName(), + JOptionPane.ERROR_MESSAGE); + e.printStackTrace(); + } + return null; + } + + /** + * Reads envInfo.txt, to set a table. + * + * @param decDir Unzipped directory + * @return Return the result reads + */ + private boolean readEnvInfo(final File decDir) { + BufferedReader read = null; + try { + File file = new File(decDir, FILE_ENVINFO); + if (!file.exists()) { + return false; + } + read = new BufferedReader(new FileReader(file)); + + String line = read.readLine(); + int i = 0; + while (line != null) { + String[] row = new String[2]; + String[] tmp = line.split("="); + + row[0] = tmp[0]; + switch (i) { + case 0: + // Collection date + SimpleDateFormat sdf = new SimpleDateFormat( + GuiCommon.DATE_FORMAT); + row[1] = sdf.format(Long.parseLong(tmp[1])); + break; + case 1: + // Log Trigger + if (tmp[1].equals("1")) { + row[1] = "ResourceExhausted"; + trigger = TRIGGER_RESOURCE_EXHAUSTED; + } else if (tmp[1].equals("2")) { + row[1] = "Signal"; + trigger = TRIGGER_SIGNAL; + } else if (tmp[1].equals("4")) { + row[1] = "Deadlock"; + trigger = TRIGGER_DEADLOCK; + } else { + row[1] = "N/A"; + } + break; + default: + if (tmp.length > 1) { + StringBuilder sb = new StringBuilder(); + for (int n = 1; n < tmp.length; n++) { + sb.append(tmp[n]); + sb.append("="); + } + row[1] = sb.substring(0, sb.length() - 1); + } else { + row[1] = "N/A"; + } + break; + } + + model.addRow(row); + line = read.readLine(); + i++; + } + return true; + } catch (Throwable e) { + GuiCommon.showMessage(guimain, GuiCommon.BASEE08, FILE_ENVINFO, + JOptionPane.ERROR_MESSAGE); + clear(); + e.printStackTrace(); + } finally { + try { + if (read != null) { + read.close(); + } + } catch (IOException e) { + GuiCommon.showMessage(guimain, GuiCommon.BASEE08, FILE_ENVINFO, + JOptionPane.ERROR_MESSAGE); + clear(); + e.printStackTrace(); + } + } + return false; + } + + /** + * Read the log file that is set in the properties file. + * + * @param decDir Unzipped directory + * @return Return the result reads + */ + private boolean readLogFiles(final File decDir) { + BufferedReader read = null; + boolean ret = true; + try { + if (GuiCommon.getLogfiles() == null) { + return ret; + } + + for (String view : GuiCommon.getLogfiles().split(",")) { + if (view.length() == 0) { + ret = false; + continue; + } + File file = new File(decDir, view); + + Object[] row = new Object[COL_COUNT]; + row[0] = file.getName(); + if (!file.exists()) { + row[1] = "N/A"; + model.addRow(row); + ret = false; + continue; + } + read = new BufferedReader(new FileReader(file)); + + String line = read.readLine(); + StringBuilder sb = new StringBuilder(); + sb.append(line); + line = read.readLine(); + if (line != null) { + sb.append("..."); + } + + row[1] = sb.toString(); + row[COL_IDX_PATH] = file.getAbsolutePath(); + + model.addRow(row); + + read.close(); + } + return ret; + } catch (Throwable e) { + GuiCommon.showMessage(guimain, GuiCommon.BASEE08, + GuiCommon.getLogfiles(), JOptionPane.ERROR_MESSAGE); + ret = false; + clear(); + } finally { + try { + if (read != null) { + read.close(); + } + } catch (IOException e) { + GuiCommon.showMessage(guimain, GuiCommon.BASEE08, + GuiCommon.getLogfiles(), JOptionPane.ERROR_MESSAGE); + ret = false; + e.printStackTrace(); + } + } + + return ret; + } + + /** + * Read the socket file that is set in the properties file. + * + * @param decDir Unzipped directory + * @return Return the result reads + */ + private boolean readSocketEndpoint(final File decDir) { + BufferedReader read = null; + BufferedWriter write = null; + boolean ret = false; + + try { + File sockFile = new File(decDir, SOCKET_ITEMNAME); + Object[] row = new Object[COL_COUNT]; + row[0] = SOCKET_ITEMNAME; + + if (GuiCommon.getSocketend() == null) { + return !ret; + } + + for (String name : GuiCommon.getSocketend().split(",")) { + File file = new File(decDir, name); + if (!file.exists() || name.length() == 0) { + continue; + } + + if (write == null) { + write = new BufferedWriter(new FileWriter(sockFile)); + } + + read = new BufferedReader(new FileReader(file)); + read.readLine(); + + if (!file.getName().endsWith("6")) { + // IPv4 + writeSocket(write, read, file.getName(), true); + } else { + // IPv6 + writeSocket(write, read, file.getName(), false); + } + + read.close(); + ret = true; + } + if (write != null) { + write.flush(); + } + + if (ret) { + row[1] = HEAD_PROTO + "..."; + row[COL_IDX_PATH] = sockFile.getAbsolutePath(); + model.addRow(row); + } + + return ret; + } catch (Throwable e) { + GuiCommon.showMessage(guimain, GuiCommon.BASEE08, + GuiCommon.getSocketend(), JOptionPane.ERROR_MESSAGE); + ret = false; + e.printStackTrace(); + } finally { + try { + if (read != null) { + read.close(); + } + if (write != null) { + write.close(); + } + } catch (IOException e) { + GuiCommon.showMessage(guimain, GuiCommon.BASEE08, + GuiCommon.getSocketend(), JOptionPane.ERROR_MESSAGE); + ret = false; + clear(); + e.printStackTrace(); + } + } + return ret; + } + + /** + * Extracts information from files deadlock the thread dump. + * + * @param decDir The directory that contains the thread dump file + * @return Return the result of extraction + */ + private boolean readThreadDump(final File decDir) { + boolean ret = true; + + if (trigger != TRIGGER_DEADLOCK) { + return ret; + } + + Object[] row = new Object[COL_COUNT]; + row[0] = DEADLOCK_ITEMNAME; + + File dumpFile = new File(decDir, GuiCommon.THREAD_DUNM_FILE); + File lockFile = new File(decDir, DEADLOCK_ITEMNAME); + + if (!dumpFile.exists()) { + return ret; + } + + row[1] = "[Summary] ..."; + row[COL_IDX_PATH] = lockFile.getAbsolutePath() + + GuiCommon.SPLIT_CHARACTER + dumpFile.getAbsolutePath(); + + if (lockFile.exists()) { + model.addRow(row); + return ret; + } + + BufferedReader read = null; + BufferedWriter write = null; + try { + read = new BufferedReader(new FileReader(dumpFile)); + String line = read.readLine(); + + boolean isJvmti = false; + ThreadData thread = null; + Map<String, ThreadData> tmpMap = new HashMap<String, ThreadData>(); + + while (line != null) { + // Name of its own thread + int classIndex = line.indexOf("\""); + if (classIndex != -1) { + thread = new ThreadData(); + thread.setThreadName(line.substring(classIndex + 1, + line.indexOf("\"", classIndex + 1))); + } + + // Thread state + if (thread != null + && line.indexOf("java.lang.Thread.State") != -1) { + String[] split = line.trim().split(" "); + if (!split[1].trim().equals("BLOCKED")) { + thread = null; + } + } + + // Class name Method name + if (thread != null && (line.trim().indexOf("at") == 0)) { + String[] split = line.trim().split(" "); + String classMethod = split[1].split("\\(")[0]; + thread.setMethodName(classMethod.substring(classMethod + .lastIndexOf(".") + 1)); + thread.setClassName(classMethod.substring(0, + classMethod.lastIndexOf("."))); + } + + // wait Address or name thread + if (thread != null && line.indexOf("- waiting to lock") != -1) { + if (isJvmti || line.indexOf("owner:") != -1) { + // jvmti + isJvmti = true; + thread.setWaitThread(line.substring( + line.indexOf(":") + 1, line.indexOf(">"))); + } else { + // socket + thread.setWaitLock(line.substring( + line.indexOf("<") + 1, line.indexOf(">"))); + } + } + // lockObject address or threadName + if (thread != null && line.indexOf("- locked") != -1) { + if (isJvmti) { + // jvmti sets the thread name + thread.setLockThread(thread.getThreadName()); + } else { + // socket address + thread.setLockThread(line.substring( + line.indexOf("<") + 1, line.indexOf(">"))); + } + tmpMap.put(thread.getLockThread(), thread); + thread = null; + } + + if (thread != null + && line.indexOf("Found one Java-level deadlock") != -1) { + break; + } + line = read.readLine(); + } + + write = new BufferedWriter(new FileWriter(lockFile)); + + if (!tmpMap.isEmpty()) { + writeThreadDump(tmpMap, write, isJvmti); + + model.addRow(row); + } + } catch (IOException e) { + GuiCommon.showMessage(guimain, GuiCommon.BASEE08, + dumpFile.getName(), JOptionPane.ERROR_MESSAGE); + ret = false; + e.printStackTrace(); + } catch (Throwable e) { + GuiCommon.showMessage(guimain, GuiCommon.BASEE08, + dumpFile.getName(), JOptionPane.ERROR_MESSAGE); + ret = false; + e.printStackTrace(); + } finally { + try { + if (read != null) { + read.close(); + } + if (write != null) { + write.close(); + } + } catch (IOException e) { + GuiCommon.showMessage(guimain, GuiCommon.BASEE08, + dumpFile.getName(), JOptionPane.ERROR_MESSAGE); + ret = false; + clear(); + e.printStackTrace(); + } + } + + return ret; + } + + /** + * Create a file that shows the status of each protocol sockets. + * + * @param write The socket file buffer for writing + * @param read Socket endpoints file(tcp,udp,tcp6,udp6) + * @param name Protocol name + * @param v4 IP version flag true:IPv4, false:IPv6 + * @throws IOException If an I/O error occurs + */ + private void writeSocket(final BufferedWriter write, + final BufferedReader read, final String name, final boolean v4) + throws IOException { + write.write(HEAD_PROTO); + write.write(HEAD_RECV_Q); + write.write(HEAD_SEND_Q); + if (v4) { + write.write(HEAD_V4_LOCAL); + write.write(HEAD_V4_FOREIGN); + } else { + write.write(HEAD_V6_LOCAL); + write.write(HEAD_V6_FOREIGN); + } + write.write(HEAD_STATE); + + write.newLine(); + String line = read.readLine(); + while (line != null) { + write.write(name); + writeBlank(write, HEAD_PROTO.length(), name.length()); + + String[] data = line.trim().split(" "); + + // Recv_Q + String[] tmp = data[4].split(":"); + String queue = Integer.toHexString(Integer.parseInt(tmp[1], + HEX_STARING)); + write.write(queue); + writeBlank(write, HEAD_RECV_Q.length(), queue.length()); + + // Send_Q + queue = Integer.toHexString(Integer.parseInt(tmp[0], HEX_STARING)); + write.write(queue); + writeBlank(write, HEAD_SEND_Q.length(), queue.length()); + + // Local Address + tmp = data[1].split(":"); + StringBuilder buf = new StringBuilder(); + if (v4) { + buf.append(hexstringToIPv4(tmp[0])); + } else { + buf.append(hexstringToIPv6(tmp[0])); + } + buf.append(":"); + buf.append(Integer.parseInt(tmp[1], HEX_STARING)); + write.write(buf.toString()); + if (v4) { + writeBlank(write, HEAD_V4_LOCAL.length(), buf.length()); + } else { + writeBlank(write, HEAD_V6_LOCAL.length(), buf.length()); + } + + // Foreign Address + tmp = data[2].split(":"); + buf.setLength(0); + if (v4) { + buf.append(hexstringToIPv4(tmp[0])); + } else { + buf.append(hexstringToIPv6(tmp[0])); + } + buf.append(":"); + buf.append(Integer.parseInt(tmp[1], HEX_STARING)); + write.write(buf.toString()); + if (v4) { + writeBlank(write, HEAD_V4_FOREIGN.length(), buf.length()); + } else { + writeBlank(write, HEAD_V6_FOREIGN.length(), buf.length()); + } + + // connection state + writeState(write, Integer.parseInt(data[3], HEX_STARING)); + + write.newLine(); + + line = read.readLine(); + } + write.newLine(); + } + + /** + * Output a summary of the deadlock. + * + * @param threadMap Information of the thread that caused the deadlock + * @param write The thread dump file buffer for writing + * @param isJvmti If true, the output type of the thread dump file has been + * using the jvmti + * @throws IOException If an I/O error occurs + */ + private void writeThreadDump(final Map<String, ThreadData> threadMap, + final BufferedWriter write, final boolean isJvmti) + throws IOException { + + int classLength = HEAD_THREAD_CLASS.length() + 2; + int methodLength = HEAD_THREAD_METHOD.length() + 2; + int threadLength = HEAD_THREAD_THREAD.length() + 2; + for (Map.Entry<String, ThreadData> entry : threadMap.entrySet()) { + int tmp = entry.getValue().getClassName().length(); + if (classLength < tmp) { + classLength = tmp + 2; + } + tmp = entry.getValue().getMethodName().length(); + if (methodLength < tmp) { + methodLength = tmp + 2; + } + tmp = entry.getValue().getThreadName().length(); + if (threadLength < tmp) { + threadLength = tmp + 2; + } + } + + write.write("[Summary]"); + write.newLine(); + + write.write(HEAD_THREAD_CLASS); + writeBlank(write, classLength, HEAD_THREAD_CLASS.length()); + write.write(HEAD_THREAD_METHOD); + writeBlank(write, methodLength, HEAD_THREAD_METHOD.length()); + write.write(HEAD_THREAD_THREAD); + writeBlank(write, threadLength, HEAD_THREAD_THREAD.length()); + write.write(HEAD_THREAD_WAIT); + write.newLine(); + + for (Map.Entry<String, ThreadData> entry : threadMap.entrySet()) { + // class Name + write.write(entry.getValue().getClassName()); + writeBlank(write, classLength, entry.getValue().getClassName() + .length()); + + // method Name + write.write(entry.getValue().getMethodName()); + writeBlank(write, methodLength, entry.getValue().getMethodName() + .length()); + + // thread + write.write(entry.getValue().getThreadName()); + writeBlank(write, threadLength, entry.getValue().getThreadName() + .length()); + + // wait-thread + if (isJvmti) { + write.write(entry.getValue().getWaitThread()); + } else { + write.write(threadMap.get(entry.getValue().getWaitLock()) + .getThreadName()); + } + write.newLine(); + } + + write.newLine(); + write.write("[Detail]"); + write.newLine(); + } + + /** + * Setting up a blank to fill the specified size. + * + * @param write The socket file buffer for writing + * @param length Header length of a single item + * @param strLen The length of a character string to write in + * @throws IOException If an I/O error occurs + */ + private void writeBlank(final BufferedWriter write, final int length, + final int strLen) throws IOException { + for (int i = 0; i < (length - strLen); i++) { + write.write(" "); + } + } + + /** + * That converts decimal IPv4 of the IPv4 in hex. + * + * @param data IPv4 before conversion + * @return The IPv4 of the converted + */ + private String hexstringToIPv4(final String data) { + + StringBuilder ipv4 = new StringBuilder(); + try { + ipv4.append(Integer.parseInt(data.substring(6, 8), HEX_STARING)); + ipv4.append("."); + ipv4.append(Integer.parseInt(data.substring(4, 6), HEX_STARING)); + ipv4.append("."); + ipv4.append(Integer.parseInt(data.substring(2, 4), HEX_STARING)); + ipv4.append("."); + ipv4.append(Integer.parseInt(data.substring(0, 2), HEX_STARING)); + } catch (NumberFormatException e) { + ipv4.setLength(0); + } + + return ipv4.toString(); + } + + /** + * That converts decimal IPv6 of the IPv6 in hex. + * + * @param data IPv6 before conversion + * @return The IPv6 of the converted + */ + private String hexstringToIPv6(final String data) { + StringBuilder ipv6 = new StringBuilder(); + + String hex = data.substring(6, 8) + data.substring(4, 6); + ipv6.append(Integer.toHexString(Integer.parseInt(hex, HEX_STARING))); + ipv6.append(":"); + + hex = data.substring(2, 4) + data.substring(0, 2); + ipv6.append(Integer.toHexString(Integer.parseInt(hex, HEX_STARING))); + ipv6.append(":"); + + hex = data.substring(14, 16) + data.substring(12, 14); + ipv6.append(Integer.toHexString(Integer.parseInt(hex, HEX_STARING))); + ipv6.append(":"); + + hex = data.substring(10, 12) + data.substring(8, 10); + ipv6.append(Integer.toHexString(Integer.parseInt(hex, HEX_STARING))); + ipv6.append(":"); + + hex = data.substring(22, 24) + data.substring(20, 22); + ipv6.append(Integer.toHexString(Integer.parseInt(hex, HEX_STARING))); + ipv6.append(":"); + + hex = data.substring(18, 20) + data.substring(16, 18); + ipv6.append(Integer.toHexString(Integer.parseInt(hex, HEX_STARING))); + ipv6.append(":"); + + hex = data.substring(30, 32) + data.substring(28, 30); + ipv6.append(Integer.toHexString(Integer.parseInt(hex, HEX_STARING))); + ipv6.append(":"); + + hex = data.substring(26, 28) + data.substring(24, 26); + ipv6.append(Integer.toHexString(Integer.parseInt(hex, HEX_STARING))); + + return ipv6.toString(); + } + + /** + * Convert a numeric string from Socket status. + * + * @param write Socket information text file + * @param state Socket status. + * @throws IOException If an I/O error occurs + */ + private void writeState(final BufferedWriter write, final int state) + throws IOException { + switch (state) { + case VAL_ESTABLISHED: + write.write(ESTABLISHED); + break; + case VAL_SYN_SENT: + write.write(SYN_SENT); + break; + case VAL_SYN_RECV: + write.write(SYN_RECV); + break; + case VAL_FIN_WAIT1: + write.write(FIN_WAIT1); + break; + case VAL_FIN_WAIT2: + write.write(FIN_WAIT2); + break; + case VAL_TIME_WAIT: + write.write(TIME_WAIT); + break; + case VAL_CLOSE: + write.write(CLOSE); + break; + case VAL_CLOSE_WAIT: + write.write(CLOSE_WAIT); + break; + case VAL_LAST_ACK: + write.write(LAST_ACK); + break; + case VAL_LISTEN: + write.write(LISTEN); + break; + case VAL_CLOSING: + write.write(CLOSING); + break; + default: + write.write("-"); + break; + } + } +}
--- a/analyzer/src/jp/co/ntt/oss/heapstats/gui/ResourceDialog.java Mon Jun 24 11:42:50 2013 +0900 +++ b/analyzer/src/jp/co/ntt/oss/heapstats/gui/ResourceDialog.java Mon Jun 24 18:06:21 2013 -0700 @@ -1,1014 +1,1014 @@ -/* - * ResourceDialog.java - * Created on 2012/01/20 - * - * Copyright (C) 2011-2013 Nippon Telegraph and Telephone Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program 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 for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -package jp.co.ntt.oss.heapstats.gui; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.FlowLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.text.NumberFormat; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.swing.BorderFactory; -import javax.swing.Box; -import javax.swing.JCheckBox; -import javax.swing.JDialog; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JSplitPane; -import javax.swing.JTable; -import javax.swing.SwingUtilities; -import javax.swing.SwingWorker; -import javax.swing.table.DefaultTableModel; - -import org.jfree.chart.ChartFactory; -import org.jfree.chart.ChartPanel; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.StandardChartTheme; -import org.jfree.chart.axis.CategoryAxis; -import org.jfree.chart.axis.CategoryLabelPositions; -import org.jfree.chart.axis.NumberAxis; -import org.jfree.chart.plot.CategoryMarker; -import org.jfree.chart.plot.CategoryPlot; -import org.jfree.chart.plot.DatasetRenderingOrder; -import org.jfree.chart.plot.PlotOrientation; -import org.jfree.chart.renderer.category.LineAndShapeRenderer; -import org.jfree.data.category.DefaultCategoryDataset; - -/** - * extends {@link JDialog}<br> - * implements {@link ActionListener}<br> - * <br> - * Draw a graphical representation of the java process resources. - */ -public class ResourceDialog extends JDialog implements - ActionListener { - - /** serialVersionUID. */ - private static final long serialVersionUID = -2143023955517445278L; - - /** Mainframe heapstats. */ - private GUIMain guimain; - - /** Angle of the axis labels. */ - private static final double ANGLE = 6.0; - - /** The index of the collection date in csv file(Collection time). */ - private static final int COLLECT_DATE = 0; - - /** The index of the collection date in csv file(java user time). */ - private static final int JAVA_CPU_USER = 2; - - /** The index of the collection date in csv file(java system time). */ - private static final int JAVA_CPU_SYSTEM = 3; - - /** The index of the collection date in csv file(VSZ). */ - private static final int JAVA_VSZ = 4; - - /** The index of the collection date in csv file(RSS). */ - private static final int JAVA_RSS = 5; - - /** The index of the collection date in csv file(user time). */ - private static final int CPU_USER = 6; - - /** The index of the collection date in csv file(user time nice). */ - private static final int CPU_USER_NICE = 7; - - /** The index of the collection date in csv file(system time). */ - private static final int CPU_SYSTEM = 8; - - /** The index of the collection date in csv file(idle task). */ - private static final int CPU_IDLE = 9; - - /** The index of the collection date in csv file(iowait ). */ - private static final int CPU_IO = 10; - - /** The index of the collection date in csv file(Interrupt ReQuest). */ - private static final int CPU_IRQ = 11; - - /** The index of the collection date in csv file(Soft Interrupt ReQuest). */ - private static final int CPU_SOFT_IRQ = 12; - - /** The index of the collection date in csv file(CPU steal). */ - private static final int CPU_STEAL = 13; - - /** The index of the collection date in csv file(CPU Guest). */ - private static final int CPU_GUEST = 14; - - /** - * The index of the collection date in csv file(Conflict Monitor - * occurrences). - */ - private static final int CONFLICT_MONITOR = 15; - - /** The index of the collection date in csv file(safepointtime). */ - private static final int SAFE_POINT_TIME = 16; - - /** The index of the collection date in csv file(safepoints). */ - private static final int SAFE_POINTS = 17; - - /** The index of the collection date in csv file(threads live). */ - private static final int THREADS_LIVE = 18; - - /** The index of the collection date in csv file(file name). */ - private static final int ARCHIVE_FILE = 19; - - /** LogDetail Data. */ - private LogDetailDialog detailDlg; - - /** Main Component. */ - private Box comp = Box.createVerticalBox(); - - /** Check box to set whether the graph of JavaCPU. */ - private JCheckBox javaCpu; - - /** Check box to set whether the graph of systemCPU. */ - private JCheckBox sysCpu; - - /** Check box to set whether the graph of JavaMem. */ - private JCheckBox javaMem; - - /** Check box to set whether the graph of threads. */ - private JCheckBox threads; - - /** Split pane at the top of the resource. */ - private JSplitPane top; - - /** Split pane at the bottom of the resource. */ - private JSplitPane bottom; - - /** Vertical split pane Resources. */ - private JSplitPane center; - - /** Chart panel JavaCPU. */ - private ChartPanel javaCPUchart; - - /** Chart panel SystemCPU. */ - private ChartPanel sysCPUchart; - - /** Chart panel JavaMemory. */ - private ChartPanel memChart; - - /** Chart panel threads. */ - private ChartPanel threadChart; - - /** Summary table model for the process display. */ - private DefaultTableModel model; - - /** The SwingWorker for drawing graphs. */ - private ResouceWorker worker; - - /** - * Creates a modeless dialog with the specified Dialog as its owner. - * - * @param owner the owner Dialog from which the dialog is displayed or null - * if this dialog has no owner - * @param dialog the LogDetail dialog - */ - public ResourceDialog(final GUIMain owner, final LogDetailDialog dialog) { - guimain = owner; - detailDlg = dialog; - - setTitle(GuiCommon.getResources() - .getString(GuiCommon.TAB_TITLE_RESOUCE)); - setSize(GuiCommon.DEFAULT_DIALOG_WIDTH, GuiCommon.DEFAULT_DIALOG_HEIGHT); - setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); - setModal(false); - - ChartFactory.setChartTheme(StandardChartTheme.createLegacyTheme()); - - comp.setBorder(BorderFactory.createEmptyBorder(GuiCommon.BORDER_SIZE, - GuiCommon.BORDER_SIZE, GuiCommon.BORDER_SIZE, - GuiCommon.BORDER_SIZE)); - setLocationByPlatform(true); - } - - /** - * Return the component. - * - * @return Return the Component - */ - public final Box getComp() { - return comp; - } - - /** - * Sets the dialog component. - * - * @param value the Main Component - */ - public final void setComp(final Box value) { - comp = value; - add(comp); - } - - /** - * Starts drawing the Resource Data. - * - * @param files csv list of selected files - * @param dataMap Key is Date. Data is the index of variable files & combo - * box. - * @param startIndex Starting date of the drawing area - * @param endIndex Ending date of the drawing area - */ - public final void draw(final List<File> files, - final Map<String, Integer[]> dataMap, final int startIndex, - final int endIndex) { - clear(); - addComponent(); - - int idx = 0; - Map<File, List<Integer>> rowIndexes = new HashMap<File, List<Integer>>(); - List<File> fileList = new ArrayList<File>(); - for (Map.Entry<String, Integer[]> entry : dataMap.entrySet()) { - if (idx >= startIndex && idx <= endIndex) { - Integer[] data = entry.getValue(); - File file = files.get(data[0]); - - List<Integer> rowList = rowIndexes.get(file); - if (rowList == null) { - rowList = new ArrayList<Integer>(); - fileList.add(file); - } - - rowList.add(data[1]); - rowIndexes.put(file, rowList); - } - idx++; - } - - if (rowIndexes.size() > 0) { - - worker = new ResouceWorker(this, rowIndexes, fileList, - (endIndex + 1) - startIndex); - worker.execute(); - } - } - - /** - * Returns true if this task completed. Completion may be due to normal - * termination, an exception, or cancellation -- in all of these cases, this - * method will return true. - * - * @return true if this task completed - */ - public final boolean isDone() { - if (worker != null) { - return worker.isDone(); - } - return true; - } - - @Override - public final void actionPerformed(final ActionEvent actionevent) { - Object eventSource = actionevent.getSource(); - - if (eventSource.equals(javaCpu)) { - if (javaCpu.isSelected()) { - top.setLeftComponent(javaCPUchart); - } else { - top.setLeftComponent(null); - } - if (!javaCpu.isSelected() && !sysCpu.isSelected()) { - center.setTopComponent(null); - } else { - center.setTopComponent(top); - } - } else if (eventSource.equals(sysCpu)) { - if (sysCpu.isSelected()) { - top.setRightComponent(sysCPUchart); - } else { - top.setRightComponent(null); - } - if (!javaCpu.isSelected() && !sysCpu.isSelected()) { - center.setTopComponent(null); - } else { - center.setTopComponent(top); - } - } else if (eventSource.equals(javaMem)) { - if (javaMem.isSelected()) { - bottom.setLeftComponent(memChart); - } else { - bottom.setLeftComponent(null); - } - if (!javaMem.isSelected() && !threads.isSelected()) { - center.setBottomComponent(null); - } else { - center.setBottomComponent(bottom); - } - } else if (eventSource.equals(threads)) { - if (threads.isSelected()) { - bottom.setRightComponent(threadChart); - } else { - bottom.setRightComponent(null); - } - if (!javaMem.isSelected() && !threads.isSelected()) { - center.setBottomComponent(null); - } else { - center.setBottomComponent(bottom); - } - } - } - - /** - * Create components to draw on the screen. - */ - private void addComponent() { - comp.add(addGraphPanel()); - comp.revalidate(); - comp.add(Box.createVerticalStrut(GuiCommon.BORDER_SIZE)); - comp.add(addSummaryPanel()); - comp.revalidate(); - } - - /** - * Create a component of the process to return the report. - * - * @return Return the accordion panel component - */ - private ExpansionContractionPanel addSummaryPanel() { - ExpansionContractionPanel threadSummary = new ExpansionContractionPanel( - GuiCommon.getResources().getString( - GuiCommon.TITLE_THREAD_SUMMARY)); - - model = new DefaultTableModel(); - model.setColumnCount(2); - model.setRowCount(0); - JTable entries = new JTable(model); - - threadSummary.setComponent(entries, false); - - return threadSummary; - } - - /** - * Create a component of the resource to return the report. - * - * @return Return the accordion panel component - */ - private ExpansionContractionPanel addGraphPanel() { - ExpansionContractionPanel graphMain = new ExpansionContractionPanel( - GuiCommon.getResources().getString( - GuiCommon.TITLE_RESOURCE_REPORT)); - JPanel graphPanel = new JPanel(new BorderLayout()); - - JPanel checkPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); - checkPanel.setBackground(Color.WHITE); - javaCpu = new JCheckBox(GuiCommon.getResources().getString( - GuiCommon.GRAPH_JAVA_CPU), true); - sysCpu = new JCheckBox(GuiCommon.getResources().getString( - GuiCommon.GRAPH_SYSTEM_CPU), true); - javaMem = new JCheckBox(GuiCommon.getResources().getString( - GuiCommon.GRAPH_JAVA_MEMORY), true); - threads = new JCheckBox(GuiCommon.getResources().getString( - GuiCommon.GRAPH_THREADS), true); - - javaCpu.setBackground(Color.WHITE); - sysCpu.setBackground(Color.WHITE); - javaMem.setBackground(Color.WHITE); - threads.setBackground(Color.WHITE); - - javaCpu.addActionListener(this); - sysCpu.addActionListener(this); - javaMem.addActionListener(this); - threads.addActionListener(this); - - checkPanel.add(javaCpu); - checkPanel.add(sysCpu); - checkPanel.add(javaMem); - checkPanel.add(threads); - - top = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); - bottom = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); - center = new JSplitPane(JSplitPane.VERTICAL_SPLIT, top, bottom); - - top.setDividerSize(5); - bottom.setDividerSize(5); - center.setDividerSize(5); - - top.setResizeWeight(0.5); - bottom.setResizeWeight(0.5); - center.setResizeWeight(0.5); - - graphPanel.add(checkPanel, BorderLayout.NORTH); - graphPanel.add(center, BorderLayout.CENTER); - - graphMain.setComponent(graphPanel, true); - - return graphMain; - } - - /** - * Clear the resource data. - */ - public final void clear() { - for (Component obj : comp.getComponents()) { - comp.remove(obj); - } - comp.setVisible(false); - - detailDlg.clear(); - } - - /** - * extends {@link SwingWorker}<br> - * <br> - * SwingWorker thread drawing done in the time-consuming process chart. - */ - private class ResouceWorker extends SwingWorker<Object, Object> { - /** the alpha transparency (must be in the range 0.0f to 1.0f). */ - private static final float ALPHA_TRANSPARENCY = 0.7f; - - /** ResourceDialog Data. */ - private ResourceDialog resourceDlg; - - /** rowindex list. */ - private Map<File, List<Integer>> rowIndexes; - - /** CSV file an ordered list of reading. */ - private List<File> fileList; - - /** Chart data sets javaCPU. */ - private DefaultCategoryDataset javaCpu; - - /** Chart data sets SystemCPU. */ - private DefaultCategoryDataset systemCpu; - - /** Chart data sets javaMemory. */ - private DefaultCategoryDataset javaMem; - - /** data sets threads,monitor and safepoints. */ - private DefaultCategoryDataset threads; - - /** data sets safepointtime. */ - private DefaultCategoryDataset safeTime; - - /** The number of data to be rendered. */ - private int rowCount; - - /** ProgressBar. */ - private HeapProgressBar progressBar; - - /** The format of the time you draw on screen. */ - public static final String CHART_DATE_FORMAT = "MMdd HH:mm:ss"; - - /*** - * Create a SwingWorker. - * - * @param dialog Resource Data - * @param indexes rowindex list - * @param files CSV file to be read list - * @param count The number of data to be rendered - */ - public ResouceWorker(final ResourceDialog dialog, - final Map<File, List<Integer>> indexes, final List<File> files, - final int count) { - resourceDlg = dialog; - rowIndexes = indexes; - fileList = files; - rowCount = count; - - // The resource of a graph is initialized. - initJavaCPU(); - initSystemCPU(); - initJavaMemory(); - initThreads(); - } - - @Override - protected Object doInBackground() throws Exception { - List<String> zipFile = new ArrayList<String>(); - List<String> hideCol = new ArrayList<String>(); - SimpleDateFormat sdf = new SimpleDateFormat(CHART_DATE_FORMAT); - progressBar = new HeapProgressBar("Draw the 'Log Collect'.", - guimain); - progressBar.setVisible(true); - - try { - float cpuAve = 0; - float cpuPeak = 0; - long vszAve = 0; - long vszPeak = 0; - long rssAve = 0; - long rssPeak = 0; - - int count = 0; - - long[] last = null; - for (File file : fileList) { - BufferedReader read = new BufferedReader(new FileReader( - file)); - - List<Integer> range = rowIndexes.get(file); - String line = read.readLine(); - int idx = 0; - while (line != null) { - String[] tmp = line.split(","); - long[] current = stringToLong(tmp); - - if (range.contains(idx)) { - if (last != null) { - // Java CPU - drawJavaCPU(current, last, tmp[ARCHIVE_FILE] - .trim().length()); - drawSystemCPU(current, last, tmp[ARCHIVE_FILE] - .trim().length()); - drawThreads(current, last, tmp[ARCHIVE_FILE] - .trim().length()); - float cpu = getCpuUtilization(current, last); - cpuAve += cpu; - cpuPeak = checkPeak(cpuPeak, cpu); - } - drawJavaMemory(current, tmp[ARCHIVE_FILE].trim() - .length()); - - vszAve += current[JAVA_VSZ]; - vszPeak = (long) checkPeak(vszPeak, - current[JAVA_VSZ]); - rssAve += current[JAVA_RSS]; - rssPeak = (long) checkPeak(rssPeak, - current[JAVA_RSS]); - - if (tmp[ARCHIVE_FILE].trim().length() > 0) { - zipFile.add(tmp[ARCHIVE_FILE + 1] - + File.separator + tmp[ARCHIVE_FILE]); - } - - if (((rowCount / 10) > 0) - && (count % (rowCount / 10) != 0)) { - hideCol.add(sdf.format(current[COLLECT_DATE])); - } - - count++; - - float value = (float) count / (float) rowCount - * 100; - progressBar.setValue((int) value); - } - - last = current.clone(); - - // One line is read. - line = read.readLine(); - - idx++; - } - - read.close(); - } - - hideCategoryLabel(javaCPUchart.getChart().getCategoryPlot() - .getDomainAxis(), hideCol); - hideCategoryLabel(sysCPUchart.getChart().getCategoryPlot() - .getDomainAxis(), hideCol); - hideCategoryLabel(memChart.getChart().getCategoryPlot() - .getDomainAxis(), hideCol); - hideCategoryLabel(threadChart.getChart().getCategoryPlot() - .getDomainAxis(), hideCol); - - createTable(cpuAve, cpuPeak, vszAve, vszPeak, rssAve, rssPeak, - count); - - detailDlg.draw(zipFile, 0); - - } catch (Throwable e) { - GuiCommon.showMessage(resourceDlg, GuiCommon.BASEE20, - JOptionPane.ERROR_MESSAGE); - e.printStackTrace(); - } - - return null; - } - - @Override - protected void done() { - super.done(); - progressBar.setVisible(false); - if (resourceDlg.isVisible()) { - comp.setVisible(true); - } - comp.revalidate(); - - resourceDlg.validate(); - } - - /** - * Convert a string to Long. - * - * @param row A list of one row of data in a csv file - * @return Return the Long list - */ - private long[] stringToLong(final String[] row) { - long[] ret = new long[row.length]; - - for (int i = 0; i < row.length; i++) { - if (!row[i].isEmpty() && row[i].matches("\\d+")) { - ret[i] = Long.parseLong(row[i]); - } - } - - return ret; - } - - /** - * Returns the system utilization cpu. - * - * @param current Current data obtained from csv - * @param last csv data obtained from previous - * @return Returns the system utilization cpu. - */ - private long getCpuUtilization(final long[] current, final long[] last) { - float total = (current[CPU_USER] - last[CPU_USER]) - + (current[CPU_USER_NICE] - last[CPU_USER_NICE]) - + (current[CPU_SYSTEM] - last[CPU_SYSTEM]) - + (current[CPU_IDLE] - last[CPU_IDLE]) - + (current[CPU_IO] - last[CPU_IO]) - + (current[CPU_IRQ] - last[CPU_IRQ]) - + (current[CPU_SOFT_IRQ] - last[CPU_SOFT_IRQ]) - + (current[CPU_STEAL] - last[CPU_STEAL]) - + (current[CPU_GUEST] - last[CPU_GUEST]); - float java = (current[JAVA_CPU_SYSTEM] - last[JAVA_CPU_SYSTEM]) - + (current[JAVA_CPU_USER] - last[JAVA_CPU_USER]); - - return (long) ((java / total) * 100); - } - - /** - * Create a summary table of the process. - * - * @param cpuAve Average CPU utilization - * @param cpuPeak Peak CPU utilization - * @param vszAve Average virtual memory usage - * @param vszPeak Peak virtual memory usage - * @param rssAve Average physical memory usage - * @param rssPeak Peak physical memory usage - * @param count Data count - */ - private void createTable(final float cpuAve, final float cpuPeak, - final long vszAve, final long vszPeak, final long rssAve, - final long rssPeak, final int count) { - Object[] row = new Object[2]; - - NumberFormat nbf = NumberFormat.getIntegerInstance(); - - row[0] = GuiCommon.getResources().getObject( - GuiCommon.ITEM_CPU_AVERAGE); - row[1] = cpuAve / (count - 1) + " %"; - model.addRow(row); - row[0] = GuiCommon.getResources() - .getObject(GuiCommon.ITEM_CPU_PEAK); - row[1] = cpuPeak + " %"; - model.addRow(row); - row[0] = GuiCommon.getResources().getObject( - GuiCommon.ITEM_VSZ_AVERAGE); - row[1] = nbf.format(vszAve / count / GuiCommon.BINARY_PREFIX) - + " KB"; - model.addRow(row); - row[0] = GuiCommon.getResources() - .getObject(GuiCommon.ITEM_VSZ_PEAK); - row[1] = nbf.format(vszPeak / GuiCommon.BINARY_PREFIX) + " KB"; - model.addRow(row); - row[0] = GuiCommon.getResources().getObject( - GuiCommon.ITEM_RSS_AVERAGE); - row[1] = nbf.format(rssAve / count / GuiCommon.BINARY_PREFIX) - + " KB"; - model.addRow(row); - row[0] = GuiCommon.getResources() - .getObject(GuiCommon.ITEM_RSS_PEAK); - row[1] = nbf.format(rssPeak / GuiCommon.BINARY_PREFIX) + " KB"; - model.addRow(row); - } - - /** - * Check the size of values. - * - * @param current Comparison value - * @param value Comparison value - * @return Returns the larger value. - */ - private float checkPeak(final float current, final float value) { - if (current < value) { - return value; - } - return current; - } - - /** - * Initialize the Java CPU chart. - */ - private void initJavaCPU() { - javaCpu = new DefaultCategoryDataset(); - JFreeChart chart = ChartFactory.createStackedAreaChart(GuiCommon - .getResources().getString(GuiCommon.GRAPH_JAVA_CPU), "", - "CPU(%)", javaCpu, PlotOrientation.VERTICAL, true, true, - true); - chart.setBackgroundPaint(Color.WHITE); - chart.getCategoryPlot().setBackgroundPaint( - new Color(GuiCommon.getBgColor())); - javaCPUchart = new ChartPanel(chart); - - top.setLeftComponent(javaCPUchart); - } - - /** - * Draw the Java CPU chart. - * - * @param current The current value - * @param last The last value - * @param line current row number retrieved in a csv file - */ - private void drawJavaCPU(final long[] current, final long[] last, - final int line) { - Runnable draw = new Runnable() { - - @Override - public void run() { - SimpleDateFormat sdf = new SimpleDateFormat( - CHART_DATE_FORMAT); - - double user = current[JAVA_CPU_USER] - last[JAVA_CPU_USER]; - double system = current[JAVA_CPU_SYSTEM] - - last[JAVA_CPU_SYSTEM]; - - javaCpu.addValue((user / (user + system)) * 100, "user", - sdf.format(current[COLLECT_DATE])); - javaCpu.addValue((system / (user + system)) * 100, - "system", sdf.format(current[COLLECT_DATE])); - - if (line > ARCHIVE_FILE) { - line(javaCPUchart.getChart().getCategoryPlot(), - sdf.format(current[COLLECT_DATE])); - } - } - }; - - if (SwingUtilities.isEventDispatchThread()) { - draw.run(); - } else { - SwingUtilities.invokeLater(draw); - } - } - - /** - * Initialize the System CPU chart. - */ - private void initSystemCPU() { - systemCpu = new DefaultCategoryDataset(); - JFreeChart chart = ChartFactory.createStackedAreaChart(GuiCommon - .getResources().getString(GuiCommon.GRAPH_SYSTEM_CPU), "", - "CPU(%)", systemCpu, PlotOrientation.VERTICAL, true, true, - true); - chart.setBackgroundPaint(Color.WHITE); - chart.getCategoryPlot().setBackgroundPaint( - new Color(GuiCommon.getBgColor())); - sysCPUchart = new ChartPanel(chart); - - top.setRightComponent(sysCPUchart); - } - - /** - * Draw the System CPU chart. - * - * @param current The current value - * @param last The last value - * @param line current row number retrieved in a csv file - */ - private void drawSystemCPU(final long[] current, final long[] last, - final int line) { - Runnable draw = new Runnable() { - - @Override - public void run() { - SimpleDateFormat sdf = new SimpleDateFormat( - CHART_DATE_FORMAT); - - float user = current[CPU_USER] - last[CPU_USER]; - float nice = current[CPU_USER_NICE] - last[CPU_USER_NICE]; - float system = current[CPU_SYSTEM] - last[CPU_SYSTEM]; - float idle = current[CPU_IDLE] - last[CPU_IDLE]; - float io = current[CPU_IO] - last[CPU_IO]; - float irq = current[CPU_IRQ] - last[CPU_IRQ]; - float soft = current[CPU_SOFT_IRQ] - last[CPU_SOFT_IRQ]; - float steal = current[CPU_STEAL] - last[CPU_STEAL]; - float guest = current[CPU_GUEST] - last[CPU_GUEST]; - - double denominator = user + nice + system + idle + io + irq - + soft + steal + guest; - - systemCpu.addValue(user / denominator * 100, "user", - sdf.format(current[COLLECT_DATE])); - systemCpu.addValue(nice / denominator * 100, "nice", - sdf.format(current[COLLECT_DATE])); - systemCpu.addValue(system / denominator * 100, "system", - sdf.format(current[COLLECT_DATE])); - systemCpu.addValue(idle / denominator * 100, "idle", - sdf.format(current[COLLECT_DATE])); - systemCpu.addValue(io / denominator * 100, "I/O", - sdf.format(current[COLLECT_DATE])); - systemCpu.addValue(irq / denominator * 100, "irq", - sdf.format(current[COLLECT_DATE])); - systemCpu.addValue(soft / denominator * 100, "softirq", - sdf.format(current[COLLECT_DATE])); - systemCpu.addValue(steal / denominator * 100, "steal", - sdf.format(current[COLLECT_DATE])); - systemCpu.addValue(guest / denominator * 100, "guest", - sdf.format(current[COLLECT_DATE])); - - if (line > ARCHIVE_FILE) { - line(sysCPUchart.getChart().getCategoryPlot(), - sdf.format(current[COLLECT_DATE])); - } - } - }; - - if (SwingUtilities.isEventDispatchThread()) { - draw.run(); - } else { - SwingUtilities.invokeLater(draw); - } - } - - /** - * Initialize the java memory chart. - */ - private void initJavaMemory() { - javaMem = new DefaultCategoryDataset(); - JFreeChart chart = ChartFactory.createLineChart(GuiCommon - .getResources().getString(GuiCommon.GRAPH_JAVA_MEMORY), "", - "Memory(KB)", javaMem, PlotOrientation.VERTICAL, true, - true, true); - chart.setBackgroundPaint(Color.WHITE); - chart.getCategoryPlot().setBackgroundPaint( - new Color(GuiCommon.getBgColor())); - memChart = new ChartPanel(chart); - - bottom.setLeftComponent(memChart); - } - - /** - * Draw the Java memory chart. - * - * @param current The current value - * @param line current row number retrieved in a csv file - */ - private void drawJavaMemory(final long[] current, final int line) { - Runnable draw = new Runnable() { - - @Override - public void run() { - SimpleDateFormat sdf = new SimpleDateFormat( - CHART_DATE_FORMAT); - javaMem.addValue(current[JAVA_RSS] - / GuiCommon.BINARY_PREFIX, "RSS(KB)", - sdf.format(current[COLLECT_DATE])); - javaMem.addValue(current[JAVA_VSZ] - / GuiCommon.BINARY_PREFIX, "VSZ(KB)", - sdf.format(current[COLLECT_DATE])); - - if (line > ARCHIVE_FILE) { - line(memChart.getChart().getCategoryPlot(), - sdf.format(current[COLLECT_DATE])); - } - } - }; - - if (SwingUtilities.isEventDispatchThread()) { - draw.run(); - } else { - SwingUtilities.invokeLater(draw); - } - } - - /** - * Initialize the Threads chart. - */ - private void initThreads() { - this.threads = new DefaultCategoryDataset(); - this.safeTime = new DefaultCategoryDataset(); - JFreeChart chart = ChartFactory.createLineChart(GuiCommon - .getResources().getString(GuiCommon.GRAPH_THREADS), "", "", - this.threads, PlotOrientation.VERTICAL, true, true, true); - chart.setBackgroundPaint(Color.WHITE); - chart.getCategoryPlot().setBackgroundPaint( - new Color(GuiCommon.getBgColor())); - - CategoryPlot plot = chart.getCategoryPlot(); - plot.setDataset(2, this.safeTime); - plot.mapDatasetToRangeAxis(2, 2); - NumberAxis axis = new NumberAxis("Time(msec)"); - axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - plot.setRangeAxis(2, axis); - plot.setDatasetRenderingOrder(DatasetRenderingOrder.REVERSE); - - LineAndShapeRenderer renderer = new LineAndShapeRenderer(); - renderer.setSeriesShapesVisible(0, false); - renderer.setSeriesShapesVisible(1, false); - plot.setRenderer(2, renderer); - - threadChart = new ChartPanel(chart); - - bottom.setRightComponent(threadChart); - } - - /** - * Draw the threads chart. - * - * @param current The current value - * @param last The last value - * @param line current row number retrieved in a csv file - */ - private void drawThreads(final long[] current, final long[] last, - final int line) { - Runnable draw = new Runnable() { - - @Override - public void run() { - SimpleDateFormat sdf = new SimpleDateFormat( - CHART_DATE_FORMAT); - - threads.addValue(current[THREADS_LIVE], "threads", - sdf.format(current[COLLECT_DATE])); - threads.addValue(current[CONFLICT_MONITOR] - - last[CONFLICT_MONITOR], "monitor", - sdf.format(current[COLLECT_DATE])); - threads.addValue(current[SAFE_POINTS] - last[SAFE_POINTS], - "safepoints", sdf.format(current[COLLECT_DATE])); - // safepointTime - safeTime.addValue(current[SAFE_POINT_TIME] - - last[SAFE_POINT_TIME], "safepointtime(msec)", - sdf.format(current[COLLECT_DATE])); - - if (line > ARCHIVE_FILE) { - line(threadChart.getChart().getCategoryPlot(), - sdf.format(current[COLLECT_DATE])); - } - } - }; - - if (SwingUtilities.isEventDispatchThread()) { - draw.run(); - } else { - SwingUtilities.invokeLater(draw); - } - } - - /** - * Draw a vertical line on the chart. - * - * @param plot To draw a line plot - * @param date Logging date - */ - private void line(final CategoryPlot plot, final String date) { - CategoryMarker marker = new CategoryMarker(date); - marker.setPaint(Color.WHITE); - marker.setAlpha(ALPHA_TRANSPARENCY); - plot.addDomainMarker(marker); - } - - /** - * Hide unwanted items out of the X axis label. - * - * @param ca CategoryAxis - * @param hideLabel Hide item list - */ - private void hideCategoryLabel(final CategoryAxis ca, - final List<String> hideLabel) { - ca.setAxisLineVisible(false); - ca.setCategoryLabelPositions(CategoryLabelPositions - .createUpRotationLabelPositions(Math.PI / ANGLE)); - - for (String label : hideLabel) { - ca.setTickLabelPaint(label, new Color(0, 0, 0, 0)); - } - } - } -} +/* + * ResourceDialog.java + * Created on 2012/01/20 + * + * Copyright (C) 2011-2013 Nippon Telegraph and Telephone Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +package jp.co.ntt.oss.heapstats.gui; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.FlowLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.text.NumberFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.JCheckBox; +import javax.swing.JDialog; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JSplitPane; +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.SwingWorker; +import javax.swing.table.DefaultTableModel; + +import org.jfree.chart.ChartFactory; +import org.jfree.chart.ChartPanel; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.StandardChartTheme; +import org.jfree.chart.axis.CategoryAxis; +import org.jfree.chart.axis.CategoryLabelPositions; +import org.jfree.chart.axis.NumberAxis; +import org.jfree.chart.plot.CategoryMarker; +import org.jfree.chart.plot.CategoryPlot; +import org.jfree.chart.plot.DatasetRenderingOrder; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.renderer.category.LineAndShapeRenderer; +import org.jfree.data.category.DefaultCategoryDataset; + +/** + * extends {@link JDialog}<br> + * implements {@link ActionListener}<br> + * <br> + * Draw a graphical representation of the java process resources. + */ +public class ResourceDialog extends JDialog implements + ActionListener { + + /** serialVersionUID. */ + private static final long serialVersionUID = -2143023955517445278L; + + /** Mainframe heapstats. */ + private GUIMain guimain; + + /** Angle of the axis labels. */ + private static final double ANGLE = 6.0; + + /** The index of the collection date in csv file(Collection time). */ + private static final int COLLECT_DATE = 0; + + /** The index of the collection date in csv file(java user time). */ + private static final int JAVA_CPU_USER = 2; + + /** The index of the collection date in csv file(java system time). */ + private static final int JAVA_CPU_SYSTEM = 3; + + /** The index of the collection date in csv file(VSZ). */ + private static final int JAVA_VSZ = 4; + + /** The index of the collection date in csv file(RSS). */ + private static final int JAVA_RSS = 5; + + /** The index of the collection date in csv file(user time). */ + private static final int CPU_USER = 6; + + /** The index of the collection date in csv file(user time nice). */ + private static final int CPU_USER_NICE = 7; + + /** The index of the collection date in csv file(system time). */ + private static final int CPU_SYSTEM = 8; + + /** The index of the collection date in csv file(idle task). */ + private static final int CPU_IDLE = 9; + + /** The index of the collection date in csv file(iowait ). */ + private static final int CPU_IO = 10; + + /** The index of the collection date in csv file(Interrupt ReQuest). */ + private static final int CPU_IRQ = 11; + + /** The index of the collection date in csv file(Soft Interrupt ReQuest). */ + private static final int CPU_SOFT_IRQ = 12; + + /** The index of the collection date in csv file(CPU steal). */ + private static final int CPU_STEAL = 13; + + /** The index of the collection date in csv file(CPU Guest). */ + private static final int CPU_GUEST = 14; + + /** + * The index of the collection date in csv file(Conflict Monitor + * occurrences). + */ + private static final int CONFLICT_MONITOR = 15; + + /** The index of the collection date in csv file(safepointtime). */ + private static final int SAFE_POINT_TIME = 16; + + /** The index of the collection date in csv file(safepoints). */ + private static final int SAFE_POINTS = 17; + + /** The index of the collection date in csv file(threads live). */ + private static final int THREADS_LIVE = 18; + + /** The index of the collection date in csv file(file name). */ + private static final int ARCHIVE_FILE = 19; + + /** LogDetail Data. */ + private LogDetailDialog detailDlg; + + /** Main Component. */ + private Box comp = Box.createVerticalBox(); + + /** Check box to set whether the graph of JavaCPU. */ + private JCheckBox javaCpu; + + /** Check box to set whether the graph of systemCPU. */ + private JCheckBox sysCpu; + + /** Check box to set whether the graph of JavaMem. */ + private JCheckBox javaMem; + + /** Check box to set whether the graph of threads. */ + private JCheckBox threads; + + /** Split pane at the top of the resource. */ + private JSplitPane top; + + /** Split pane at the bottom of the resource. */ + private JSplitPane bottom; + + /** Vertical split pane Resources. */ + private JSplitPane center; + + /** Chart panel JavaCPU. */ + private ChartPanel javaCPUchart; + + /** Chart panel SystemCPU. */ + private ChartPanel sysCPUchart; + + /** Chart panel JavaMemory. */ + private ChartPanel memChart; + + /** Chart panel threads. */ + private ChartPanel threadChart; + + /** Summary table model for the process display. */ + private DefaultTableModel model; + + /** The SwingWorker for drawing graphs. */ + private ResouceWorker worker; + + /** + * Creates a modeless dialog with the specified Dialog as its owner. + * + * @param owner the owner Dialog from which the dialog is displayed or null + * if this dialog has no owner + * @param dialog the LogDetail dialog + */ + public ResourceDialog(final GUIMain owner, final LogDetailDialog dialog) { + guimain = owner; + detailDlg = dialog; + + setTitle(GuiCommon.getResources() + .getString(GuiCommon.TAB_TITLE_RESOUCE)); + setSize(GuiCommon.DEFAULT_DIALOG_WIDTH, GuiCommon.DEFAULT_DIALOG_HEIGHT); + setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); + setModal(false); + + ChartFactory.setChartTheme(StandardChartTheme.createLegacyTheme()); + + comp.setBorder(BorderFactory.createEmptyBorder(GuiCommon.BORDER_SIZE, + GuiCommon.BORDER_SIZE, GuiCommon.BORDER_SIZE, + GuiCommon.BORDER_SIZE)); + setLocationByPlatform(true); + } + + /** + * Return the component. + * + * @return Return the Component + */ + public final Box getComp() { + return comp; + } + + /** + * Sets the dialog component. + * + * @param value the Main Component + */ + public final void setComp(final Box value) { + comp = value; + add(comp); + } + + /** + * Starts drawing the Resource Data. + * + * @param files csv list of selected files + * @param dataMap Key is Date. Data is the index of variable files & combo + * box. + * @param startIndex Starting date of the drawing area + * @param endIndex Ending date of the drawing area + */ + public final void draw(final List<File> files, + final Map<String, Integer[]> dataMap, final int startIndex, + final int endIndex) { + clear(); + addComponent(); + + int idx = 0; + Map<File, List<Integer>> rowIndexes = new HashMap<File, List<Integer>>(); + List<File> fileList = new ArrayList<File>(); + for (Map.Entry<String, Integer[]> entry : dataMap.entrySet()) { + if (idx >= startIndex && idx <= endIndex) { + Integer[] data = entry.getValue(); + File file = files.get(data[0]); + + List<Integer> rowList = rowIndexes.get(file); + if (rowList == null) { + rowList = new ArrayList<Integer>(); + fileList.add(file); + } + + rowList.add(data[1]); + rowIndexes.put(file, rowList); + } + idx++; + } + + if (rowIndexes.size() > 0) { + + worker = new ResouceWorker(this, rowIndexes, fileList, + (endIndex + 1) - startIndex); + worker.execute(); + } + } + + /** + * Returns true if this task completed. Completion may be due to normal + * termination, an exception, or cancellation -- in all of these cases, this + * method will return true. + * + * @return true if this task completed + */ + public final boolean isDone() { + if (worker != null) { + return worker.isDone(); + } + return true; + } + + @Override + public final void actionPerformed(final ActionEvent actionevent) { + Object eventSource = actionevent.getSource(); + + if (eventSource.equals(javaCpu)) { + if (javaCpu.isSelected()) { + top.setLeftComponent(javaCPUchart); + } else { + top.setLeftComponent(null); + } + if (!javaCpu.isSelected() && !sysCpu.isSelected()) { + center.setTopComponent(null); + } else { + center.setTopComponent(top); + } + } else if (eventSource.equals(sysCpu)) { + if (sysCpu.isSelected()) { + top.setRightComponent(sysCPUchart); + } else { + top.setRightComponent(null); + } + if (!javaCpu.isSelected() && !sysCpu.isSelected()) { + center.setTopComponent(null); + } else { + center.setTopComponent(top); + } + } else if (eventSource.equals(javaMem)) { + if (javaMem.isSelected()) { + bottom.setLeftComponent(memChart); + } else { + bottom.setLeftComponent(null); + } + if (!javaMem.isSelected() && !threads.isSelected()) { + center.setBottomComponent(null); + } else { + center.setBottomComponent(bottom); + } + } else if (eventSource.equals(threads)) { + if (threads.isSelected()) { + bottom.setRightComponent(threadChart); + } else { + bottom.setRightComponent(null); + } + if (!javaMem.isSelected() && !threads.isSelected()) { + center.setBottomComponent(null); + } else { + center.setBottomComponent(bottom); + } + } + } + + /** + * Create components to draw on the screen. + */ + private void addComponent() { + comp.add(addGraphPanel()); + comp.revalidate(); + comp.add(Box.createVerticalStrut(GuiCommon.BORDER_SIZE)); + comp.add(addSummaryPanel()); + comp.revalidate(); + } + + /** + * Create a component of the process to return the report. + * + * @return Return the accordion panel component + */ + private ExpansionContractionPanel addSummaryPanel() { + ExpansionContractionPanel threadSummary = new ExpansionContractionPanel( + GuiCommon.getResources().getString( + GuiCommon.TITLE_THREAD_SUMMARY)); + + model = new DefaultTableModel(); + model.setColumnCount(2); + model.setRowCount(0); + JTable entries = new JTable(model); + + threadSummary.setComponent(entries, false); + + return threadSummary; + } + + /** + * Create a component of the resource to return the report. + * + * @return Return the accordion panel component + */ + private ExpansionContractionPanel addGraphPanel() { + ExpansionContractionPanel graphMain = new ExpansionContractionPanel( + GuiCommon.getResources().getString( + GuiCommon.TITLE_RESOURCE_REPORT)); + JPanel graphPanel = new JPanel(new BorderLayout()); + + JPanel checkPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); + checkPanel.setBackground(Color.WHITE); + javaCpu = new JCheckBox(GuiCommon.getResources().getString( + GuiCommon.GRAPH_JAVA_CPU), true); + sysCpu = new JCheckBox(GuiCommon.getResources().getString( + GuiCommon.GRAPH_SYSTEM_CPU), true); + javaMem = new JCheckBox(GuiCommon.getResources().getString( + GuiCommon.GRAPH_JAVA_MEMORY), true); + threads = new JCheckBox(GuiCommon.getResources().getString( + GuiCommon.GRAPH_THREADS), true); + + javaCpu.setBackground(Color.WHITE); + sysCpu.setBackground(Color.WHITE); + javaMem.setBackground(Color.WHITE); + threads.setBackground(Color.WHITE); + + javaCpu.addActionListener(this); + sysCpu.addActionListener(this); + javaMem.addActionListener(this); + threads.addActionListener(this); + + checkPanel.add(javaCpu); + checkPanel.add(sysCpu); + checkPanel.add(javaMem); + checkPanel.add(threads); + + top = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); + bottom = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); + center = new JSplitPane(JSplitPane.VERTICAL_SPLIT, top, bottom); + + top.setDividerSize(5); + bottom.setDividerSize(5); + center.setDividerSize(5); + + top.setResizeWeight(0.5); + bottom.setResizeWeight(0.5); + center.setResizeWeight(0.5); + + graphPanel.add(checkPanel, BorderLayout.NORTH); + graphPanel.add(center, BorderLayout.CENTER); + + graphMain.setComponent(graphPanel, true); + + return graphMain; + } + + /** + * Clear the resource data. + */ + public final void clear() { + for (Component obj : comp.getComponents()) { + comp.remove(obj); + } + comp.setVisible(false); + + detailDlg.clear(); + } + + /** + * extends {@link SwingWorker}<br> + * <br> + * SwingWorker thread drawing done in the time-consuming process chart. + */ + private class ResouceWorker extends SwingWorker<Object, Object> { + /** the alpha transparency (must be in the range 0.0f to 1.0f). */ + private static final float ALPHA_TRANSPARENCY = 0.7f; + + /** ResourceDialog Data. */ + private ResourceDialog resourceDlg; + + /** rowindex list. */ + private Map<File, List<Integer>> rowIndexes; + + /** CSV file an ordered list of reading. */ + private List<File> fileList; + + /** Chart data sets javaCPU. */ + private DefaultCategoryDataset javaCpu; + + /** Chart data sets SystemCPU. */ + private DefaultCategoryDataset systemCpu; + + /** Chart data sets javaMemory. */ + private DefaultCategoryDataset javaMem; + + /** data sets threads,monitor and safepoints. */ + private DefaultCategoryDataset threads; + + /** data sets safepointtime. */ + private DefaultCategoryDataset safeTime; + + /** The number of data to be rendered. */ + private int rowCount; + + /** ProgressBar. */ + private HeapProgressBar progressBar; + + /** The format of the time you draw on screen. */ + public static final String CHART_DATE_FORMAT = "MMdd HH:mm:ss"; + + /*** + * Create a SwingWorker. + * + * @param dialog Resource Data + * @param indexes rowindex list + * @param files CSV file to be read list + * @param count The number of data to be rendered + */ + public ResouceWorker(final ResourceDialog dialog, + final Map<File, List<Integer>> indexes, final List<File> files, + final int count) { + resourceDlg = dialog; + rowIndexes = indexes; + fileList = files; + rowCount = count; + + // The resource of a graph is initialized. + initJavaCPU(); + initSystemCPU(); + initJavaMemory(); + initThreads(); + } + + @Override + protected Object doInBackground() throws Exception { + List<String> zipFile = new ArrayList<String>(); + List<String> hideCol = new ArrayList<String>(); + SimpleDateFormat sdf = new SimpleDateFormat(CHART_DATE_FORMAT); + progressBar = new HeapProgressBar("Draw the 'Log Collect'.", + guimain); + progressBar.setVisible(true); + + try { + float cpuAve = 0; + float cpuPeak = 0; + long vszAve = 0; + long vszPeak = 0; + long rssAve = 0; + long rssPeak = 0; + + int count = 0; + + long[] last = null; + for (File file : fileList) { + BufferedReader read = new BufferedReader(new FileReader( + file)); + + List<Integer> range = rowIndexes.get(file); + String line = read.readLine(); + int idx = 0; + while (line != null) { + String[] tmp = line.split(","); + long[] current = stringToLong(tmp); + + if (range.contains(idx)) { + if (last != null) { + // Java CPU + drawJavaCPU(current, last, tmp[ARCHIVE_FILE] + .trim().length()); + drawSystemCPU(current, last, tmp[ARCHIVE_FILE] + .trim().length()); + drawThreads(current, last, tmp[ARCHIVE_FILE] + .trim().length()); + float cpu = getCpuUtilization(current, last); + cpuAve += cpu; + cpuPeak = checkPeak(cpuPeak, cpu); + } + drawJavaMemory(current, tmp[ARCHIVE_FILE].trim() + .length()); + + vszAve += current[JAVA_VSZ]; + vszPeak = (long) checkPeak(vszPeak, + current[JAVA_VSZ]); + rssAve += current[JAVA_RSS]; + rssPeak = (long) checkPeak(rssPeak, + current[JAVA_RSS]); + + if (tmp[ARCHIVE_FILE].trim().length() > 0) { + zipFile.add(tmp[ARCHIVE_FILE + 1] + + File.separator + tmp[ARCHIVE_FILE]); + } + + if (((rowCount / 10) > 0) + && (count % (rowCount / 10) != 0)) { + hideCol.add(sdf.format(current[COLLECT_DATE])); + } + + count++; + + float value = (float) count / (float) rowCount + * 100; + progressBar.setValue((int) value); + } + + last = current.clone(); + + // One line is read. + line = read.readLine(); + + idx++; + } + + read.close(); + } + + hideCategoryLabel(javaCPUchart.getChart().getCategoryPlot() + .getDomainAxis(), hideCol); + hideCategoryLabel(sysCPUchart.getChart().getCategoryPlot() + .getDomainAxis(), hideCol); + hideCategoryLabel(memChart.getChart().getCategoryPlot() + .getDomainAxis(), hideCol); + hideCategoryLabel(threadChart.getChart().getCategoryPlot() + .getDomainAxis(), hideCol); + + createTable(cpuAve, cpuPeak, vszAve, vszPeak, rssAve, rssPeak, + count); + + detailDlg.draw(zipFile, 0); + + } catch (Throwable e) { + GuiCommon.showMessage(resourceDlg, GuiCommon.BASEE20, + JOptionPane.ERROR_MESSAGE); + e.printStackTrace(); + } + + return null; + } + + @Override + protected void done() { + super.done(); + progressBar.setVisible(false); + if (resourceDlg.isVisible()) { + comp.setVisible(true); + } + comp.revalidate(); + + resourceDlg.validate(); + } + + /** + * Convert a string to Long. + * + * @param row A list of one row of data in a csv file + * @return Return the Long list + */ + private long[] stringToLong(final String[] row) { + long[] ret = new long[row.length]; + + for (int i = 0; i < row.length; i++) { + if (!row[i].isEmpty() && row[i].matches("\\d+")) { + ret[i] = Long.parseLong(row[i]); + } + } + + return ret; + } + + /** + * Returns the system utilization cpu. + * + * @param current Current data obtained from csv + * @param last csv data obtained from previous + * @return Returns the system utilization cpu. + */ + private long getCpuUtilization(final long[] current, final long[] last) { + float total = (current[CPU_USER] - last[CPU_USER]) + + (current[CPU_USER_NICE] - last[CPU_USER_NICE]) + + (current[CPU_SYSTEM] - last[CPU_SYSTEM]) + + (current[CPU_IDLE] - last[CPU_IDLE]) + + (current[CPU_IO] - last[CPU_IO]) + + (current[CPU_IRQ] - last[CPU_IRQ]) + + (current[CPU_SOFT_IRQ] - last[CPU_SOFT_IRQ]) + + (current[CPU_STEAL] - last[CPU_STEAL]) + + (current[CPU_GUEST] - last[CPU_GUEST]); + float java = (current[JAVA_CPU_SYSTEM] - last[JAVA_CPU_SYSTEM]) + + (current[JAVA_CPU_USER] - last[JAVA_CPU_USER]); + + return (long) ((java / total) * 100); + } + + /** + * Create a summary table of the process. + * + * @param cpuAve Average CPU utilization + * @param cpuPeak Peak CPU utilization + * @param vszAve Average virtual memory usage + * @param vszPeak Peak virtual memory usage + * @param rssAve Average physical memory usage + * @param rssPeak Peak physical memory usage + * @param count Data count + */ + private void createTable(final float cpuAve, final float cpuPeak, + final long vszAve, final long vszPeak, final long rssAve, + final long rssPeak, final int count) { + Object[] row = new Object[2]; + + NumberFormat nbf = NumberFormat.getIntegerInstance(); + + row[0] = GuiCommon.getResources().getObject( + GuiCommon.ITEM_CPU_AVERAGE); + row[1] = cpuAve / (count - 1) + " %"; + model.addRow(row); + row[0] = GuiCommon.getResources() + .getObject(GuiCommon.ITEM_CPU_PEAK); + row[1] = cpuPeak + " %"; + model.addRow(row); + row[0] = GuiCommon.getResources().getObject( + GuiCommon.ITEM_VSZ_AVERAGE); + row[1] = nbf.format(vszAve / count / GuiCommon.BINARY_PREFIX) + + " KB"; + model.addRow(row); + row[0] = GuiCommon.getResources() + .getObject(GuiCommon.ITEM_VSZ_PEAK); + row[1] = nbf.format(vszPeak / GuiCommon.BINARY_PREFIX) + " KB"; + model.addRow(row); + row[0] = GuiCommon.getResources().getObject( + GuiCommon.ITEM_RSS_AVERAGE); + row[1] = nbf.format(rssAve / count / GuiCommon.BINARY_PREFIX) + + " KB"; + model.addRow(row); + row[0] = GuiCommon.getResources() + .getObject(GuiCommon.ITEM_RSS_PEAK); + row[1] = nbf.format(rssPeak / GuiCommon.BINARY_PREFIX) + " KB"; + model.addRow(row); + } + + /** + * Check the size of values. + * + * @param current Comparison value + * @param value Comparison value + * @return Returns the larger value. + */ + private float checkPeak(final float current, final float value) { + if (current < value) { + return value; + } + return current; + } + + /** + * Initialize the Java CPU chart. + */ + private void initJavaCPU() { + javaCpu = new DefaultCategoryDataset(); + JFreeChart chart = ChartFactory.createStackedAreaChart(GuiCommon + .getResources().getString(GuiCommon.GRAPH_JAVA_CPU), "", + "CPU(%)", javaCpu, PlotOrientation.VERTICAL, true, true, + true); + chart.setBackgroundPaint(Color.WHITE); + chart.getCategoryPlot().setBackgroundPaint( + new Color(GuiCommon.getBgColor())); + javaCPUchart = new ChartPanel(chart); + + top.setLeftComponent(javaCPUchart); + } + + /** + * Draw the Java CPU chart. + * + * @param current The current value + * @param last The last value + * @param line current row number retrieved in a csv file + */ + private void drawJavaCPU(final long[] current, final long[] last, + final int line) { + Runnable draw = new Runnable() { + + @Override + public void run() { + SimpleDateFormat sdf = new SimpleDateFormat( + CHART_DATE_FORMAT); + + double user = current[JAVA_CPU_USER] - last[JAVA_CPU_USER]; + double system = current[JAVA_CPU_SYSTEM] + - last[JAVA_CPU_SYSTEM]; + + javaCpu.addValue((user / (user + system)) * 100, "user", + sdf.format(current[COLLECT_DATE])); + javaCpu.addValue((system / (user + system)) * 100, + "system", sdf.format(current[COLLECT_DATE])); + + if (line > ARCHIVE_FILE) { + line(javaCPUchart.getChart().getCategoryPlot(), + sdf.format(current[COLLECT_DATE])); + } + } + }; + + if (SwingUtilities.isEventDispatchThread()) { + draw.run(); + } else { + SwingUtilities.invokeLater(draw); + } + } + + /** + * Initialize the System CPU chart. + */ + private void initSystemCPU() { + systemCpu = new DefaultCategoryDataset(); + JFreeChart chart = ChartFactory.createStackedAreaChart(GuiCommon + .getResources().getString(GuiCommon.GRAPH_SYSTEM_CPU), "", + "CPU(%)", systemCpu, PlotOrientation.VERTICAL, true, true, + true); + chart.setBackgroundPaint(Color.WHITE); + chart.getCategoryPlot().setBackgroundPaint( + new Color(GuiCommon.getBgColor())); + sysCPUchart = new ChartPanel(chart); + + top.setRightComponent(sysCPUchart); + } + + /** + * Draw the System CPU chart. + * + * @param current The current value + * @param last The last value + * @param line current row number retrieved in a csv file + */ + private void drawSystemCPU(final long[] current, final long[] last, + final int line) { + Runnable draw = new Runnable() { + + @Override + public void run() { + SimpleDateFormat sdf = new SimpleDateFormat( + CHART_DATE_FORMAT); + + float user = current[CPU_USER] - last[CPU_USER]; + float nice = current[CPU_USER_NICE] - last[CPU_USER_NICE]; + float system = current[CPU_SYSTEM] - last[CPU_SYSTEM]; + float idle = current[CPU_IDLE] - last[CPU_IDLE]; + float io = current[CPU_IO] - last[CPU_IO]; + float irq = current[CPU_IRQ] - last[CPU_IRQ]; + float soft = current[CPU_SOFT_IRQ] - last[CPU_SOFT_IRQ]; + float steal = current[CPU_STEAL] - last[CPU_STEAL]; + float guest = current[CPU_GUEST] - last[CPU_GUEST]; + + double denominator = user + nice + system + idle + io + irq + + soft + steal + guest; + + systemCpu.addValue(user / denominator * 100, "user", + sdf.format(current[COLLECT_DATE])); + systemCpu.addValue(nice / denominator * 100, "nice", + sdf.format(current[COLLECT_DATE])); + systemCpu.addValue(system / denominator * 100, "system", + sdf.format(current[COLLECT_DATE])); + systemCpu.addValue(idle / denominator * 100, "idle", + sdf.format(current[COLLECT_DATE])); + systemCpu.addValue(io / denominator * 100, "I/O", + sdf.format(current[COLLECT_DATE])); + systemCpu.addValue(irq / denominator * 100, "irq", + sdf.format(current[COLLECT_DATE])); + systemCpu.addValue(soft / denominator * 100, "softirq", + sdf.format(current[COLLECT_DATE])); + systemCpu.addValue(steal / denominator * 100, "steal", + sdf.format(current[COLLECT_DATE])); + systemCpu.addValue(guest / denominator * 100, "guest", + sdf.format(current[COLLECT_DATE])); + + if (line > ARCHIVE_FILE) { + line(sysCPUchart.getChart().getCategoryPlot(), + sdf.format(current[COLLECT_DATE])); + } + } + }; + + if (SwingUtilities.isEventDispatchThread()) { + draw.run(); + } else { + SwingUtilities.invokeLater(draw); + } + } + + /** + * Initialize the java memory chart. + */ + private void initJavaMemory() { + javaMem = new DefaultCategoryDataset(); + JFreeChart chart = ChartFactory.createLineChart(GuiCommon + .getResources().getString(GuiCommon.GRAPH_JAVA_MEMORY), "", + "Memory(KB)", javaMem, PlotOrientation.VERTICAL, true, + true, true); + chart.setBackgroundPaint(Color.WHITE); + chart.getCategoryPlot().setBackgroundPaint( + new Color(GuiCommon.getBgColor())); + memChart = new ChartPanel(chart); + + bottom.setLeftComponent(memChart); + } + + /** + * Draw the Java memory chart. + * + * @param current The current value + * @param line current row number retrieved in a csv file + */ + private void drawJavaMemory(final long[] current, final int line) { + Runnable draw = new Runnable() { + + @Override + public void run() { + SimpleDateFormat sdf = new SimpleDateFormat( + CHART_DATE_FORMAT); + javaMem.addValue(current[JAVA_RSS] + / GuiCommon.BINARY_PREFIX, "RSS(KB)", + sdf.format(current[COLLECT_DATE])); + javaMem.addValue(current[JAVA_VSZ] + / GuiCommon.BINARY_PREFIX, "VSZ(KB)", + sdf.format(current[COLLECT_DATE])); + + if (line > ARCHIVE_FILE) { + line(memChart.getChart().getCategoryPlot(), + sdf.format(current[COLLECT_DATE])); + } + } + }; + + if (SwingUtilities.isEventDispatchThread()) { + draw.run(); + } else { + SwingUtilities.invokeLater(draw); + } + } + + /** + * Initialize the Threads chart. + */ + private void initThreads() { + this.threads = new DefaultCategoryDataset(); + this.safeTime = new DefaultCategoryDataset(); + JFreeChart chart = ChartFactory.createLineChart(GuiCommon + .getResources().getString(GuiCommon.GRAPH_THREADS), "", "", + this.threads, PlotOrientation.VERTICAL, true, true, true); + chart.setBackgroundPaint(Color.WHITE); + chart.getCategoryPlot().setBackgroundPaint( + new Color(GuiCommon.getBgColor())); + + CategoryPlot plot = chart.getCategoryPlot(); + plot.setDataset(2, this.safeTime); + plot.mapDatasetToRangeAxis(2, 2); + NumberAxis axis = new NumberAxis("Time(msec)"); + axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); + plot.setRangeAxis(2, axis); + plot.setDatasetRenderingOrder(DatasetRenderingOrder.REVERSE); + + LineAndShapeRenderer renderer = new LineAndShapeRenderer(); + renderer.setSeriesShapesVisible(0, false); + renderer.setSeriesShapesVisible(1, false); + plot.setRenderer(2, renderer); + + threadChart = new ChartPanel(chart); + + bottom.setRightComponent(threadChart); + } + + /** + * Draw the threads chart. + * + * @param current The current value + * @param last The last value + * @param line current row number retrieved in a csv file + */ + private void drawThreads(final long[] current, final long[] last, + final int line) { + Runnable draw = new Runnable() { + + @Override + public void run() { + SimpleDateFormat sdf = new SimpleDateFormat( + CHART_DATE_FORMAT); + + threads.addValue(current[THREADS_LIVE], "threads", + sdf.format(current[COLLECT_DATE])); + threads.addValue(current[CONFLICT_MONITOR] + - last[CONFLICT_MONITOR], "monitor", + sdf.format(current[COLLECT_DATE])); + threads.addValue(current[SAFE_POINTS] - last[SAFE_POINTS], + "safepoints", sdf.format(current[COLLECT_DATE])); + // safepointTime + safeTime.addValue(current[SAFE_POINT_TIME] + - last[SAFE_POINT_TIME], "safepointtime(msec)", + sdf.format(current[COLLECT_DATE])); + + if (line > ARCHIVE_FILE) { + line(threadChart.getChart().getCategoryPlot(), + sdf.format(current[COLLECT_DATE])); + } + } + }; + + if (SwingUtilities.isEventDispatchThread()) { + draw.run(); + } else { + SwingUtilities.invokeLater(draw); + } + } + + /** + * Draw a vertical line on the chart. + * + * @param plot To draw a line plot + * @param date Logging date + */ + private void line(final CategoryPlot plot, final String date) { + CategoryMarker marker = new CategoryMarker(date); + marker.setPaint(Color.WHITE); + marker.setAlpha(ALPHA_TRANSPARENCY); + plot.addDomainMarker(marker); + } + + /** + * Hide unwanted items out of the X axis label. + * + * @param ca CategoryAxis + * @param hideLabel Hide item list + */ + private void hideCategoryLabel(final CategoryAxis ca, + final List<String> hideLabel) { + ca.setAxisLineVisible(false); + ca.setCategoryLabelPositions(CategoryLabelPositions + .createUpRotationLabelPositions(Math.PI / ANGLE)); + + for (String label : hideLabel) { + ca.setTickLabelPaint(label, new Color(0, 0, 0, 0)); + } + } + } +}
--- a/analyzer/src/jp/co/ntt/oss/heapstats/gui/SelectLogfiles.java Mon Jun 24 11:42:50 2013 +0900 +++ b/analyzer/src/jp/co/ntt/oss/heapstats/gui/SelectLogfiles.java Mon Jun 24 18:06:21 2013 -0700 @@ -1,377 +1,377 @@ -/* - * SelectLogfiles.java - * Created on 2012/01/24 - * - * Copyright (C) 2011-2013 Nippon Telegraph and Telephone Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program 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 for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ -package jp.co.ntt.oss.heapstats.gui; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Cursor; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; -import java.util.Vector; - -import javax.swing.Box; -import javax.swing.BoxLayout; -import javax.swing.JButton; -import javax.swing.JComboBox; -import javax.swing.JFileChooser; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JTextField; -import javax.swing.filechooser.FileFilter; - -/** - * extends {@link ExpansionContractionPanel}<br> - * implements {@link ActionListener}<br> - * <br> - * The class reads the log file which the agent collected. - */ -public class SelectLogfiles extends ExpansionContractionPanel implements - ActionListener { - /** serialVersionUID. */ - private static final long serialVersionUID = -2247677323518295406L; - - /** Resouce Data. */ - private ResourceDialog resourceDlg; - - /** Select Data Button. */ - private JButton logSelectBtn; - - /** Dump File Names. */ - private JTextField fileNames; - - /** Select Range StartDate. */ - private JComboBox startCombo; - - /** Select Range EndDate. */ - private JComboBox endCombo; - - /** Select Range OK Button. */ - private JButton okButton; - - /** The list of log files selected in the file chooser dialog. */ - private List<File> files; - - /** Key is Date. Data is the index of variable files & combo box. */ - private Map<String, Integer[]> logMap; - - /** - * It is a screen part which reads the log file which the agent collected. - * - * @param title The title of an accordion panel - * @param dialog Resource Data - */ - public SelectLogfiles(final String title, final ResourceDialog dialog) { - super(title); - resourceDlg = dialog; - - addComponent(); - } - - @Override - public final void actionPerformed(final ActionEvent actionevent) { - Object eventSource = actionevent.getSource(); - if (!resourceDlg.isDone()) { - // Being processed - GuiCommon.showMessage(this, GuiCommon.BASEW02, - JOptionPane.WARNING_MESSAGE); - return; - } - - // SELECT DATA - if (eventSource.equals(logSelectBtn) - || actionevent.getActionCommand().equals( - GuiCommon.getResources().getString( - GuiCommon.MENU_FILE_LOGOPEN))) { - loadLogfile(); - } else if (eventSource.equals(okButton)) { - // Draws the Summary, Delta and SnapShot. - int start = startCombo.getSelectedIndex(); - int end = endCombo.getSelectedIndex(); - - if (selectRange(start, end)) { - resourceDlg.draw(files, logMap, start, end); - } - } - } - - /** - * Create components to draw on the screen. - */ - private void addComponent() { - JPanel panelMain = new JPanel(); - panelMain.setLayout(new BorderLayout(GuiCommon.BORDER_SIZE, - GuiCommon.BORDER_SIZE)); - panelMain.setBackground(Color.WHITE); - - logSelectBtn = new JButton(GuiCommon.getResources().getString( - GuiCommon.BUTTON_LOG_SELECT)); - logSelectBtn.addActionListener(this); - - // SELECT FILE - JPanel panelFile = new JPanel(); - panelFile.setLayout(new BorderLayout(GuiCommon.BORDER_SIZE, - GuiCommon.BORDER_SIZE)); - panelFile.setBackground(Color.WHITE); - - fileNames = new JTextField(); - - panelFile.add(logSelectBtn, BorderLayout.WEST); - panelFile.add(fileNames, BorderLayout.CENTER); - panelMain.add(panelFile, BorderLayout.NORTH); - - // Select Range - JPanel panelRange = new JPanel(); - okButton = new JButton("OK"); - okButton.addActionListener(this); - panelRange.setLayout(new BoxLayout(panelRange, BoxLayout.X_AXIS)); - panelRange.setBackground(Color.WHITE); - - startCombo = new JComboBox(); - startCombo.setEditable(true); - - JLabel llabel = new JLabel(" ~ "); - endCombo = new JComboBox(); - endCombo.setEditable(true); - - panelRange.add(new JLabel(GuiCommon.getResources().getString( - GuiCommon.SELECT_RANGE) - + " ")); - panelRange.add(startCombo); - panelRange.add(llabel); - panelRange.add(endCombo); - panelRange.add(Box.createVerticalStrut(GuiCommon.BORDER_SIZE)); - panelRange.add(okButton); - - panelMain.add(panelRange, BorderLayout.CENTER); - panelRange.setLayout(new BoxLayout(panelRange, BoxLayout.X_AXIS)); - - this.setComponent(panelMain, true); - } - - /** - * The log files which the agent collected is loaded. - */ - private void loadLogfile() { - JFileChooser fileDlg = getFileChooser(); - - int result = fileDlg.showOpenDialog(this); - - if (result == JFileChooser.APPROVE_OPTION) { - try { - GuiCommon.setCurrentDir(fileDlg.getCurrentDirectory()); - } catch (IOException e) { - GuiCommon.showMessage(this, GuiCommon.BASEE17, - JOptionPane.ERROR_MESSAGE); - } - - files = new ArrayList<File>(); - logMap = new TreeMap<String, Integer[]>(); - - resourceDlg.clear(); - - startCombo.removeAllItems(); - endCombo.removeAllItems(); - fileNames.setText(""); - - setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - - StringBuilder fileList = new StringBuilder(); - try { - Vector<String> dateList = new Vector<String>(); - - startCombo.removeAllItems(); - endCombo.removeAllItems(); - - SimpleDateFormat sdf = new SimpleDateFormat( - GuiCommon.DATE_FORMAT); - int fileIdx = 0; - for (File file : fileDlg.getSelectedFiles()) { - File tempFile = File.createTempFile("heapstats", null); - tempFile.deleteOnExit(); - FileOutputStream fstream = new FileOutputStream( - tempFile.getCanonicalPath(), false); - List<String> csvRows = new ArrayList<String>(); - - files.add(tempFile); - - fileList.append(" "); - fileList.append(file.getName()); - fileList.append(","); - - BufferedReader read = new BufferedReader(new FileReader( - file)); - - String line = read.readLine(); - while (line != null) { - csvRows.add(line); - // One line is read. - line = read.readLine(); - } - read.close(); - - int rowIdx = 0; - Collections.sort(csvRows); - for (String row : csvRows) { - Integer[] data = new Integer[2]; - - data[0] = fileIdx; - data[1] = rowIdx++; - - String[] rowSplit = row.split(","); - - // key: collect date, data:file & rowIndex - logMap.put(rowSplit[0], data); - - fstream.write(row.getBytes()); - fstream.write(','); - fstream.write(file.getParent().getBytes()); - fstream.write('\n'); - } - fstream.close(); - - fileIdx++; - } - - for (Map.Entry<String, Integer[]> entry : logMap.entrySet()) { - String date = sdf.format(Long.parseLong(entry.getKey())); - startCombo.addItem(date); - endCombo.addItem(date); - dateList.add(date); - } - - startCombo.setSelectedIndex(0); - endCombo.setSelectedIndex(endCombo.getItemCount() - 1); - - // KeyListener - // Set SELECT RANGE combobox - SnapshotDateListener start = new SnapshotDateListener( - startCombo); - start.setSnapList(dateList); - JTextField startTxt = (JTextField) startCombo.getEditor() - .getEditorComponent(); - startTxt.setText(startCombo.getItemAt(0).toString()); - startTxt.addKeyListener(start); - - SnapshotDateListener end = new SnapshotDateListener(endCombo); - end.setSnapList(dateList); - JTextField endTxt = (JTextField) endCombo.getEditor() - .getEditorComponent(); - endTxt.setText(endCombo.getItemAt(endCombo.getItemCount() - 1) - .toString()); - endTxt.addKeyListener(end); - fileNames.setText(fileList.toString().substring(0, - fileList.length() - 1)); - } catch (Throwable e) { - StringBuilder sb = new StringBuilder(); - for (File file : files) { - sb.append(file.getName()); - sb.append(", "); - } - GuiCommon.showMessage(this, GuiCommon.BASEE08, sb.toString() - .substring(0, sb.length() - 2), - JOptionPane.ERROR_MESSAGE); - fileList.setLength(0); - files.clear(); - logMap.clear(); - } finally { - setCursor(Cursor.getDefaultCursor()); - } - } - } - - /** - * Return the FileChooser instance. - * - * @return Return the FileChooser instance - */ - private JFileChooser getFileChooser() { - JFileChooser fileDlg = new JFileChooser(); - fileDlg.setCurrentDirectory(GuiCommon.getCurrentDir()); - fileDlg.setMultiSelectionEnabled(true); - fileDlg.setFileFilter(new FileFilter() { - - @Override - public String getDescription() { - return "CSV(*.csv, *.csv.*)"; - } - - @Override - public boolean accept(final File f) { - if (f.isDirectory()) { - return true; - } - - String name = f.getName(); - int ext = name.lastIndexOf("."); - - while (ext > 0) { - if (name.substring(ext).toLowerCase().equals(".csv")) { - return true; - } - name = name.substring(0, ext); - ext = name.lastIndexOf("."); - } - return false; - } - }); - - return fileDlg; - } - - /** - * Check the start and end snapshot of the selection period. - * - * @param start Start time of the snapshot for drawing - * @param end End time of the snapshot for drawing - * @return Return the check result. - */ - private boolean selectRange(final int start, final int end) { - if (start == -1 || end == -1) { - GuiCommon.showMessage(this, GuiCommon.BASEE05, - JOptionPane.ERROR_MESSAGE); - return false; - } else if (start > end) { - // Reversed start and end - GuiCommon.showMessage(this, GuiCommon.BASEE06, - JOptionPane.ERROR_MESSAGE); - return false; - } else if (start == end) { - // Match the start and end - GuiCommon.showMessage(this, GuiCommon.BASEE07, - JOptionPane.ERROR_MESSAGE); - return false; - } - return true; - } -} +/* + * SelectLogfiles.java + * Created on 2012/01/24 + * + * Copyright (C) 2011-2013 Nippon Telegraph and Telephone Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ +package jp.co.ntt.oss.heapstats.gui; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Cursor; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.Vector; + +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFileChooser; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.filechooser.FileFilter; + +/** + * extends {@link ExpansionContractionPanel}<br> + * implements {@link ActionListener}<br> + * <br> + * The class reads the log file which the agent collected. + */ +public class SelectLogfiles extends ExpansionContractionPanel implements + ActionListener { + /** serialVersionUID. */ + private static final long serialVersionUID = -2247677323518295406L; + + /** Resouce Data. */ + private ResourceDialog resourceDlg; + + /** Select Data Button. */ + private JButton logSelectBtn; + + /** Dump File Names. */ + private JTextField fileNames; + + /** Select Range StartDate. */ + private JComboBox startCombo; + + /** Select Range EndDate. */ + private JComboBox endCombo; + + /** Select Range OK Button. */ + private JButton okButton; + + /** The list of log files selected in the file chooser dialog. */ + private List<File> files; + + /** Key is Date. Data is the index of variable files & combo box. */ + private Map<String, Integer[]> logMap; + + /** + * It is a screen part which reads the log file which the agent collected. + * + * @param title The title of an accordion panel + * @param dialog Resource Data + */ + public SelectLogfiles(final String title, final ResourceDialog dialog) { + super(title); + resourceDlg = dialog; + + addComponent(); + } + + @Override + public final void actionPerformed(final ActionEvent actionevent) { + Object eventSource = actionevent.getSource(); + if (!resourceDlg.isDone()) { + // Being processed + GuiCommon.showMessage(this, GuiCommon.BASEW02, + JOptionPane.WARNING_MESSAGE); + return; + } + + // SELECT DATA + if (eventSource.equals(logSelectBtn) + || actionevent.getActionCommand().equals( + GuiCommon.getResources().getString( + GuiCommon.MENU_FILE_LOGOPEN))) { + loadLogfile(); + } else if (eventSource.equals(okButton)) { + // Draws the Summary, Delta and SnapShot. + int start = startCombo.getSelectedIndex(); + int end = endCombo.getSelectedIndex(); + + if (selectRange(start, end)) { + resourceDlg.draw(files, logMap, start, end); + } + } + } + + /** + * Create components to draw on the screen. + */ + private void addComponent() { + JPanel panelMain = new JPanel(); + panelMain.setLayout(new BorderLayout(GuiCommon.BORDER_SIZE, + GuiCommon.BORDER_SIZE)); + panelMain.setBackground(Color.WHITE); + + logSelectBtn = new JButton(GuiCommon.getResources().getString( + GuiCommon.BUTTON_LOG_SELECT)); + logSelectBtn.addActionListener(this); + + // SELECT FILE + JPanel panelFile = new JPanel(); + panelFile.setLayout(new BorderLayout(GuiCommon.BORDER_SIZE, + GuiCommon.BORDER_SIZE)); + panelFile.setBackground(Color.WHITE); + + fileNames = new JTextField(); + + panelFile.add(logSelectBtn, BorderLayout.WEST); + panelFile.add(fileNames, BorderLayout.CENTER); + panelMain.add(panelFile, BorderLayout.NORTH); + + // Select Range + JPanel panelRange = new JPanel(); + okButton = new JButton("OK"); + okButton.addActionListener(this); + panelRange.setLayout(new BoxLayout(panelRange, BoxLayout.X_AXIS)); + panelRange.setBackground(Color.WHITE); + + startCombo = new JComboBox(); + startCombo.setEditable(true); + + JLabel llabel = new JLabel(" ~ "); + endCombo = new JComboBox(); + endCombo.setEditable(true); + + panelRange.add(new JLabel(GuiCommon.getResources().getString( + GuiCommon.SELECT_RANGE) + + " ")); + panelRange.add(startCombo); + panelRange.add(llabel); + panelRange.add(endCombo); + panelRange.add(Box.createVerticalStrut(GuiCommon.BORDER_SIZE)); + panelRange.add(okButton); + + panelMain.add(panelRange, BorderLayout.CENTER); + panelRange.setLayout(new BoxLayout(panelRange, BoxLayout.X_AXIS)); + + this.setComponent(panelMain, true); + } + + /** + * The log files which the agent collected is loaded. + */ + private void loadLogfile() { + JFileChooser fileDlg = getFileChooser(); + + int result = fileDlg.showOpenDialog(this); + + if (result == JFileChooser.APPROVE_OPTION) { + try { + GuiCommon.setCurrentDir(fileDlg.getCurrentDirectory()); + } catch (IOException e) { + GuiCommon.showMessage(this, GuiCommon.BASEE17, + JOptionPane.ERROR_MESSAGE); + } + + files = new ArrayList<File>(); + logMap = new TreeMap<String, Integer[]>(); + + resourceDlg.clear(); + + startCombo.removeAllItems(); + endCombo.removeAllItems(); + fileNames.setText(""); + + setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + + StringBuilder fileList = new StringBuilder(); + try { + Vector<String> dateList = new Vector<String>(); + + startCombo.removeAllItems(); + endCombo.removeAllItems(); + + SimpleDateFormat sdf = new SimpleDateFormat( + GuiCommon.DATE_FORMAT); + int fileIdx = 0; + for (File file : fileDlg.getSelectedFiles()) { + File tempFile = File.createTempFile("heapstats", null); + tempFile.deleteOnExit(); + FileOutputStream fstream = new FileOutputStream( + tempFile.getCanonicalPath(), false); + List<String> csvRows = new ArrayList<String>(); + + files.add(tempFile); + + fileList.append(" "); + fileList.append(file.getName()); + fileList.append(","); + + BufferedReader read = new BufferedReader(new FileReader( + file)); + + String line = read.readLine(); + while (line != null) { + csvRows.add(line); + // One line is read. + line = read.readLine(); + } + read.close(); + + int rowIdx = 0; + Collections.sort(csvRows); + for (String row : csvRows) { + Integer[] data = new Integer[2]; + + data[0] = fileIdx; + data[1] = rowIdx++; + + String[] rowSplit = row.split(","); + + // key: collect date, data:file & rowIndex + logMap.put(rowSplit[0], data); + + fstream.write(row.getBytes()); + fstream.write(','); + fstream.write(file.getParent().getBytes()); + fstream.write('\n'); + } + fstream.close(); + + fileIdx++; + } + + for (Map.Entry<String, Integer[]> entry : logMap.entrySet()) { + String date = sdf.format(Long.parseLong(entry.getKey())); + startCombo.addItem(date); + endCombo.addItem(date); + dateList.add(date); + } + + startCombo.setSelectedIndex(0); + endCombo.setSelectedIndex(endCombo.getItemCount() - 1); + + // KeyListener + // Set SELECT RANGE combobox + SnapshotDateListener start = new SnapshotDateListener( + startCombo); + start.setSnapList(dateList); + JTextField startTxt = (JTextField) startCombo.getEditor() + .getEditorComponent(); + startTxt.setText(startCombo.getItemAt(0).toString()); + startTxt.addKeyListener(start); + + SnapshotDateListener end = new SnapshotDateListener(endCombo); + end.setSnapList(dateList); + JTextField endTxt = (JTextField) endCombo.getEditor() + .getEditorComponent(); + endTxt.setText(endCombo.getItemAt(endCombo.getItemCount() - 1) + .toString()); + endTxt.addKeyListener(end); + fileNames.setText(fileList.toString().substring(0, + fileList.length() - 1)); + } catch (Throwable e) { + StringBuilder sb = new StringBuilder(); + for (File file : files) { + sb.append(file.getName()); + sb.append(", "); + } + GuiCommon.showMessage(this, GuiCommon.BASEE08, sb.toString() + .substring(0, sb.length() - 2), + JOptionPane.ERROR_MESSAGE); + fileList.setLength(0); + files.clear(); + logMap.clear(); + } finally { + setCursor(Cursor.getDefaultCursor()); + } + } + } + + /** + * Return the FileChooser instance. + * + * @return Return the FileChooser instance + */ + private JFileChooser getFileChooser() { + JFileChooser fileDlg = new JFileChooser(); + fileDlg.setCurrentDirectory(GuiCommon.getCurrentDir()); + fileDlg.setMultiSelectionEnabled(true); + fileDlg.setFileFilter(new FileFilter() { + + @Override + public String getDescription() { + return "CSV(*.csv, *.csv.*)"; + } + + @Override + public boolean accept(final File f) { + if (f.isDirectory()) { + return true; + } + + String name = f.getName(); + int ext = name.lastIndexOf("."); + + while (ext > 0) { + if (name.substring(ext).toLowerCase().equals(".csv")) { + return true; + } + name = name.substring(0, ext); + ext = name.lastIndexOf("."); + } + return false; + } + }); + + return fileDlg; + } + + /** + * Check the start and end snapshot of the selection period. + * + * @param start Start time of the snapshot for drawing + * @param end End time of the snapshot for drawing + * @return Return the check result. + */ + private boolean selectRange(final int start, final int end) { + if (start == -1 || end == -1) { + GuiCommon.showMessage(this, GuiCommon.BASEE05, + JOptionPane.ERROR_MESSAGE); + return false; + } else if (start > end) { + // Reversed start and end + GuiCommon.showMessage(this, GuiCommon.BASEE06, + JOptionPane.ERROR_MESSAGE); + return false; + } else if (start == end) { + // Match the start and end + GuiCommon.showMessage(this, GuiCommon.BASEE07, + JOptionPane.ERROR_MESSAGE); + return false; + } + return true; + } +}
--- a/analyzer/src/jp/co/ntt/oss/heapstats/gui/SnapShotDialog.java Mon Jun 24 11:42:50 2013 +0900 +++ b/analyzer/src/jp/co/ntt/oss/heapstats/gui/SnapShotDialog.java Mon Jun 24 18:06:21 2013 -0700 @@ -1,396 +1,396 @@ -/* - * SnapShotDialog.java - * Created on 2011/10/13 - * - * Copyright (C) 2011-2013 Nippon Telegraph and Telephone Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program 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 for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -package jp.co.ntt.oss.heapstats.gui; - -import java.awt.Color; -import java.awt.Component; -import java.awt.Paint; -import java.io.IOException; -import java.text.NumberFormat; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.swing.BorderFactory; -import javax.swing.Box; -import javax.swing.JDialog; -import javax.swing.JFrame; -import javax.swing.JScrollPane; -import javax.swing.JTable; -import javax.swing.RowSorter.SortKey; -import javax.swing.SortOrder; -import javax.swing.table.DefaultTableModel; -import javax.swing.table.TableCellRenderer; -import javax.swing.table.TableModel; -import javax.swing.table.TableRowSorter; - -import jp.co.ntt.oss.heapstats.container.MapKey; -import jp.co.ntt.oss.heapstats.container.ObjectData; -import jp.co.ntt.oss.heapstats.container.SnapShot; -import jp.co.ntt.oss.heapstats.container.SnapShotHeader; -import jp.co.ntt.oss.heapstats.gui.graph.GraphColorHelper; -import jp.co.ntt.oss.heapstats.gui.snapshot.SnapShotHelper; -import jp.co.ntt.oss.heapstats.gui.snapshot.SnapShotReader; - -import org.jfree.chart.ChartFactory; -import org.jfree.chart.ChartPanel; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.plot.PiePlot; -import org.jfree.data.general.DefaultPieDataset; - -/** - * extends {@link JDialog}<br> - * <br> - * Draw the snapshot information. - */ -public class SnapShotDialog extends JDialog { - /** serialVersionUID. */ - private static final long serialVersionUID = 7336022709943040450L; - - /** Main Component. */ - private Box comp = Box.createVerticalBox(); - - /** Class of higher rank. */ - private Set<String> ranking; - - /** object lists. */ - private JTable entries; - - /** - * Creates a modeless dialog with the specified title and with the specified - * owner dialog. - * - * @param owner the owner Dialog from which the dialog is displayed or null - * if this dialog has no owner. - */ - public SnapShotDialog(final JFrame owner) { - super(owner); - - setSize(GuiCommon.DEFAULT_DIALOG_WIDTH, GuiCommon.DEFAULT_DIALOG_HEIGHT); - setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); - setModal(false); - setTitle(GuiCommon.getResources().getString( - GuiCommon.TAB_TITLE_SNAPSHOT)); - comp.setBorder(BorderFactory.createEmptyBorder(GuiCommon.BORDER_SIZE, - GuiCommon.BORDER_SIZE, GuiCommon.BORDER_SIZE, - GuiCommon.BORDER_SIZE)); - add(comp); - setLocationByPlatform(true); - } - - /** - * This method does the drawing SnapShot Data. - * - * @param data a snapshot Information - * @param search Browse Class List - * @param filter Exclusion list of classes - * @throws IOException Any of the usual Input/Output related exceptions. - * @throws ClassNotFoundException Class of a serialized object cannot be - * found. - */ - public final void draw(final List<Object> data, final Object[] search, - final List<Pattern> filter) throws IOException, - ClassNotFoundException { - comp.setVisible(false); - for (Component obj : comp.getComponents()) { - comp.remove(obj); - } - - ranking = new HashSet<String>(); - - long offset = (Long) data.get(0); - SnapShotReader snapShotReader = (SnapShotReader) data.get(1); - - // SnapShot Info - String[] tableHeader = new String[] {"", ""}; - DefaultTableModel snapShotInfoModel = new DefaultTableModel( - tableHeader, 0); - JTable snapShotInfo = new JTable(snapShotInfoModel); - - // objects List - SnapShotEntriesModel entriesModel = new SnapShotEntriesModel(); - entries = new JTable(entriesModel) { - /** serialVersionUID. */ - private static final long serialVersionUID = -925317579655004381L; - - @Override - public Component prepareRenderer(final TableCellRenderer tcr, - final int row, final int column) { - Component retValue = super.prepareRenderer(tcr, row, column); - - String name = (String) getValueAt(row, 1); - if (ranking.size() < GuiCommon.getRankLevel()) { - ranking.add(name); - } - retValue.setForeground(getForeground()); - Paint bgPaint = GraphColorHelper.getColor((String) getValueAt( - row, 1)); - if (bgPaint != null && column == 0 && ranking.contains(name)) { - retValue.setBackground((Color) bgPaint); - } else { - retValue.setBackground(Color.WHITE); - } - return retValue; - } - - @Override - public boolean isCellEditable(final int row, final int column) { - return false; - } - }; - - entries.getColumnModel().getColumn(0) - .setPreferredWidth(GuiCommon.COL_SIZE_COLOR); - entries.getColumnModel().getColumn(1) - .setPreferredWidth(GuiCommon.COL_SIZE_CLASSNAME); - - TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>( - entriesModel); - sorter.setSortable(0, false); - entries.setRowSorter(sorter); - entries.getTableHeader().setReorderingAllowed(false); - - snapShotInfoModel.setRowCount(0); - entriesModel.setRowCount(0); - - SnapShot snapShot = snapShotReader.getSnapShot(offset); - - ObjectData[] elements = SnapShotHelper.getSortedArray( - snapShot.getElements(), SnapShotHelper.SortItem.SIZE, - SnapShotHelper.SortOrder.DESC); - - // Filter Start - List<ObjectData> result = getObjectsList(elements, search, filter); - - // Sets the objects data. - for (ObjectData elmt : result) { - Object[] ary = new Object[4]; - ary[1] = elmt.getName(); - ary[2] = elmt.getCount(); - ary[3] = elmt.getTotalSize(); - entriesModel.addRow(ary); - } - - ExpansionContractionPanel snapInfo = new ExpansionContractionPanel( - GuiCommon.getResources().getString(GuiCommon.TITLE_SNAPSHOT)); - - ExpansionContractionPanel pieChart = new ExpansionContractionPanel( - GuiCommon.getResources().getString(GuiCommon.TITLE_PIECHART)); - - ExpansionContractionPanel objList = new ExpansionContractionPanel( - GuiCommon.getResources().getString(GuiCommon.TITLE_OBJECTLIST)); - - JScrollPane entryScroll = new JScrollPane(); - entryScroll.getViewport().setView(entries); - objList.setComponent(entryScroll, true); - - ArrayList<SortKey> sortKeys = new ArrayList<SortKey>(); - sortKeys.add(new SortKey(3, SortOrder.DESCENDING)); - entries.getRowSorter().setSortKeys(sortKeys); - - addComp(snapInfo); - addComp(pieChart); - addComp(objList); - - setSnapShotInfo(snapShot, snapShotInfoModel); - - snapInfo.setComponent(snapShotInfo, false); - - // draw pie chart - if ((search != null && search.length > 0) - || (filter != null && filter.size() > 0)) { - drawPieChart(snapShot, result.toArray(), pieChart, false); - } else { - drawPieChart(snapShot, result.toArray(), pieChart, true); - } - - if (this.isVisible()) { - comp.setVisible(true); - } - } - - /** - * Clear the SnapShot Data. - */ - public final void clear() { - for (Component obj : comp.getComponents()) { - comp.remove(obj); - } - comp.setVisible(false); - } - - /** - * Returns the object list of articles and then excluded. - * - * @param elements List of all objects - * @param search Browse Class List - * @param filter Exclusion list of classes - * @return Returns the object list of articles and then excluded. - */ - private List<ObjectData> getObjectsList(final ObjectData[] elements, - final Object[] search, final List<Pattern> filter) { - List<ObjectData> tmpList = new ArrayList<ObjectData>(); - List<ObjectData> result = new ArrayList<ObjectData>(); - - // Start Filter - for (ObjectData elmt : elements) { - boolean match = false; - if (filter != null) { - for (Pattern ptn : filter) { - Matcher matcher = ptn.matcher(elmt.getName()); - if (matcher.matches()) { - match = true; - break; - } - } - } - - if (!match) { - tmpList.add(elmt); - } - } - - // Start Search - for (ObjectData elmt : tmpList) { - if (search != null && search.length > 0) { - for (Object tmp : search) { - if (elmt.getName().equals(tmp)) { - result.add(elmt); - } - } - } else { - result.add(elmt); - } - } - return result; - } - - /** - * SnapShot Information on label data sets. - * - * @param snapShot SnapShot - * @param snapShotInfoModel DefaultTableModel the Objects List - */ - private void setSnapShotInfo(final SnapShot snapShot, - final DefaultTableModel snapShotInfoModel) { - SnapShotHeader hdr = snapShot.getHeader(); - - String heapUsageStr = NumberFormat.getNumberInstance().format( - snapShot.getHeapUsage() / GuiCommon.BINARY_PREFIX) - + " KB"; - - SimpleDateFormat sdf = new SimpleDateFormat(GuiCommon.DATE_FORMAT); - String[][] infoData = { - { - GuiCommon.getResources().getString( - GuiCommon.SNAPSHOTINFO_DATE), - sdf.format(hdr.getSnapShotDate())}, - { - GuiCommon.getResources().getString( - GuiCommon.SNAPSHOTINFO_ENTRYIES), - Long.toString(hdr.getNumEntries())}, - { - GuiCommon.getResources().getString( - GuiCommon.SNAPSHOTINFO_HEAP), heapUsageStr}, - { - GuiCommon.getResources().getString( - GuiCommon.SNAPSHOTINFO_CAUSE), - hdr.getCauseString()}, - { - GuiCommon.getResources().getString( - GuiCommon.SNAPSHOTINFO_GCCAUSE), - hdr.getGcCause()}}; - - String[] infoHeader = {"", ""}; - snapShotInfoModel.setDataVector(infoData, infoHeader); - } - - /** - * Draw the large object heap usage pie chart. - * - * @param snapShot SnapShot - * @param elements Objects Data - * @param pieChart ExpansionContractionPanel is to set the chart. - * @param others Other display flag. true is view. - */ - private void drawPieChart(final SnapShot snapShot, final Object[] elements, - final ExpansionContractionPanel pieChart, final boolean others) { - - DefaultPieDataset graphData = new DefaultPieDataset(); - long heapUsage = snapShot.getHeapUsage(); - for (int i = 0; (i < elements.length) && (i < GuiCommon.getRankLevel()); i++) { - ObjectData odata = (ObjectData) elements[i]; - graphData.setValue(new MapKey(odata), odata.getTotalSize()); - heapUsage -= odata.getTotalSize(); - } - - if (others) { - graphData.setValue(new MapKey(0, "Others"), heapUsage); - } - - JFreeChart chart = ChartFactory.createPieChart("", graphData, false, - true, true); - chart.setBackgroundPaint(Color.WHITE); - PiePlot plot = (PiePlot) chart.getPlot(); - plot.setBackgroundPaint(new Color(GuiCommon.getBgColor())); - plot.setLabelGenerator(null); - GraphColorHelper.adjustColor(graphData, plot); - - ChartPanel chartPanel = new ChartPanel(chart); - pieChart.setComponent(chartPanel, true); - } - - /** - * Gets the main components that you want to SnapShotDialog. - * - * @return Main component - */ - public final Box getComp() { - return comp; - } - - /** - * Sets the main components that you want to SnapShotDialog. - * - * @param value Box - */ - public final void setComp(final Box value) { - comp = value; - add(comp); - } - - /** - * The main component to be added to the specified component. - * - * @param value Component - */ - private void addComp(final Component value) { - comp.add(Box.createVerticalStrut(GuiCommon.BORDER_SIZE)); - comp.add(value); - comp.revalidate(); - } -} +/* + * SnapShotDialog.java + * Created on 2011/10/13 + * + * Copyright (C) 2011-2013 Nippon Telegraph and Telephone Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +package jp.co.ntt.oss.heapstats.gui; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Paint; +import java.io.IOException; +import java.text.NumberFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.RowSorter.SortKey; +import javax.swing.SortOrder; +import javax.swing.table.DefaultTableModel; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableModel; +import javax.swing.table.TableRowSorter; + +import jp.co.ntt.oss.heapstats.container.MapKey; +import jp.co.ntt.oss.heapstats.container.ObjectData; +import jp.co.ntt.oss.heapstats.container.SnapShot; +import jp.co.ntt.oss.heapstats.container.SnapShotHeader; +import jp.co.ntt.oss.heapstats.gui.graph.GraphColorHelper; +import jp.co.ntt.oss.heapstats.gui.snapshot.SnapShotHelper; +import jp.co.ntt.oss.heapstats.gui.snapshot.SnapShotReader; + +import org.jfree.chart.ChartFactory; +import org.jfree.chart.ChartPanel; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.plot.PiePlot; +import org.jfree.data.general.DefaultPieDataset; + +/** + * extends {@link JDialog}<br> + * <br> + * Draw the snapshot information. + */ +public class SnapShotDialog extends JDialog { + /** serialVersionUID. */ + private static final long serialVersionUID = 7336022709943040450L; + + /** Main Component. */ + private Box comp = Box.createVerticalBox(); + + /** Class of higher rank. */ + private Set<String> ranking; + + /** object lists. */ + private JTable entries; + + /** + * Creates a modeless dialog with the specified title and with the specified + * owner dialog. + * + * @param owner the owner Dialog from which the dialog is displayed or null + * if this dialog has no owner. + */ + public SnapShotDialog(final JFrame owner) { + super(owner); + + setSize(GuiCommon.DEFAULT_DIALOG_WIDTH, GuiCommon.DEFAULT_DIALOG_HEIGHT); + setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); + setModal(false); + setTitle(GuiCommon.getResources().getString( + GuiCommon.TAB_TITLE_SNAPSHOT)); + comp.setBorder(BorderFactory.createEmptyBorder(GuiCommon.BORDER_SIZE, + GuiCommon.BORDER_SIZE, GuiCommon.BORDER_SIZE, + GuiCommon.BORDER_SIZE)); + add(comp); + setLocationByPlatform(true); + } + + /** + * This method does the drawing SnapShot Data. + * + * @param data a snapshot Information + * @param search Browse Class List + * @param filter Exclusion list of classes + * @throws IOException Any of the usual Input/Output related exceptions. + * @throws ClassNotFoundException Class of a serialized object cannot be + * found. + */ + public final void draw(final List<Object> data, final Object[] search, + final List<Pattern> filter) throws IOException, + ClassNotFoundException { + comp.setVisible(false); + for (Component obj : comp.getComponents()) { + comp.remove(obj); + } + + ranking = new HashSet<String>(); + + long offset = (Long) data.get(0); + SnapShotReader snapShotReader = (SnapShotReader) data.get(1); + + // SnapShot Info + String[] tableHeader = new String[] {"", ""}; + DefaultTableModel snapShotInfoModel = new DefaultTableModel( + tableHeader, 0); + JTable snapShotInfo = new JTable(snapShotInfoModel); + + // objects List + SnapShotEntriesModel entriesModel = new SnapShotEntriesModel(); + entries = new JTable(entriesModel) { + /** serialVersionUID. */ + private static final long serialVersionUID = -925317579655004381L; + + @Override + public Component prepareRenderer(final TableCellRenderer tcr, + final int row, final int column) { + Component retValue = super.prepareRenderer(tcr, row, column); + + String name = (String) getValueAt(row, 1); + if (ranking.size() < GuiCommon.getRankLevel()) { + ranking.add(name); + } + retValue.setForeground(getForeground()); + Paint bgPaint = GraphColorHelper.getColor((String) getValueAt( + row, 1)); + if (bgPaint != null && column == 0 && ranking.contains(name)) { + retValue.setBackground((Color) bgPaint); + } else { + retValue.setBackground(Color.WHITE); + } + return retValue; + } + + @Override + public boolean isCellEditable(final int row, final int column) { + return false; + } + }; + + entries.getColumnModel().getColumn(0) + .setPreferredWidth(GuiCommon.COL_SIZE_COLOR); + entries.getColumnModel().getColumn(1) + .setPreferredWidth(GuiCommon.COL_SIZE_CLASSNAME); + + TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>( + entriesModel); + sorter.setSortable(0, false); + entries.setRowSorter(sorter); + entries.getTableHeader().setReorderingAllowed(false); + + snapShotInfoModel.setRowCount(0); + entriesModel.setRowCount(0); + + SnapShot snapShot = snapShotReader.getSnapShot(offset); + + ObjectData[] elements = SnapShotHelper.getSortedArray( + snapShot.getElements(), SnapShotHelper.SortItem.SIZE, + SnapShotHelper.SortOrder.DESC); + + // Filter Start + List<ObjectData> result = getObjectsList(elements, search, filter); + + // Sets the objects data. + for (ObjectData elmt : result) { + Object[] ary = new Object[4]; + ary[1] = elmt.getName(); + ary[2] = elmt.getCount(); + ary[3] = elmt.getTotalSize(); + entriesModel.addRow(ary); + } + + ExpansionContractionPanel snapInfo = new ExpansionContractionPanel( + GuiCommon.getResources().getString(GuiCommon.TITLE_SNAPSHOT)); + + ExpansionContractionPanel pieChart = new ExpansionContractionPanel( + GuiCommon.getResources().getString(GuiCommon.TITLE_PIECHART)); + + ExpansionContractionPanel objList = new ExpansionContractionPanel( + GuiCommon.getResources().getString(GuiCommon.TITLE_OBJECTLIST)); + + JScrollPane entryScroll = new JScrollPane(); + entryScroll.getViewport().setView(entries); + objList.setComponent(entryScroll, true); + + ArrayList<SortKey> sortKeys = new ArrayList<SortKey>(); + sortKeys.add(new SortKey(3, SortOrder.DESCENDING)); + entries.getRowSorter().setSortKeys(sortKeys); + + addComp(snapInfo); + addComp(pieChart); + addComp(objList); + + setSnapShotInfo(snapShot, snapShotInfoModel); + + snapInfo.setComponent(snapShotInfo, false); + + // draw pie chart + if ((search != null && search.length > 0) + || (filter != null && filter.size() > 0)) { + drawPieChart(snapShot, result.toArray(), pieChart, false); + } else { + drawPieChart(snapShot, result.toArray(), pieChart, true); + } + + if (this.isVisible()) { + comp.setVisible(true); + } + } + + /** + * Clear the SnapShot Data. + */ + public final void clear() { + for (Component obj : comp.getComponents()) { + comp.remove(obj); + } + comp.setVisible(false); + } + + /** + * Returns the object list of articles and then excluded. + * + * @param elements List of all objects + * @param search Browse Class List + * @param filter Exclusion list of classes + * @return Returns the object list of articles and then excluded. + */ + private List<ObjectData> getObjectsList(final ObjectData[] elements, + final Object[] search, final List<Pattern> filter) { + List<ObjectData> tmpList = new ArrayList<ObjectData>(); + List<ObjectData> result = new ArrayList<ObjectData>(); + + // Start Filter + for (ObjectData elmt : elements) { + boolean match = false; + if (filter != null) { + for (Pattern ptn : filter) { + Matcher matcher = ptn.matcher(elmt.getName()); + if (matcher.matches()) { + match = true; + break; + } + } + } + + if (!match) { + tmpList.add(elmt); + } + } + + // Start Search + for (ObjectData elmt : tmpList) { + if (search != null && search.length > 0) { + for (Object tmp : search) { + if (elmt.getName().equals(tmp)) { + result.add(elmt); + } + } + } else { + result.add(elmt); + } + } + return result; + } + + /** + * SnapShot Information on label data sets. + * + * @param snapShot SnapShot + * @param snapShotInfoModel DefaultTableModel the Objects List + */ + private void setSnapShotInfo(final SnapShot snapShot, + final DefaultTableModel snapShotInfoModel) { + SnapShotHeader hdr = snapShot.getHeader(); + + String heapUsageStr = NumberFormat.getNumberInstance().format( + snapShot.getHeapUsage() / GuiCommon.BINARY_PREFIX) + + " KB"; + + SimpleDateFormat sdf = new SimpleDateFormat(GuiCommon.DATE_FORMAT); + String[][] infoData = { + { + GuiCommon.getResources().getString( + GuiCommon.SNAPSHOTINFO_DATE), + sdf.format(hdr.getSnapShotDate())}, + { + GuiCommon.getResources().getString( + GuiCommon.SNAPSHOTINFO_ENTRYIES), + Long.toString(hdr.getNumEntries())}, + { + GuiCommon.getResources().getString( + GuiCommon.SNAPSHOTINFO_HEAP), heapUsageStr}, + { + GuiCommon.getResources().getString( + GuiCommon.SNAPSHOTINFO_CAUSE), + hdr.getCauseString()}, + { + GuiCommon.getResources().getString( + GuiCommon.SNAPSHOTINFO_GCCAUSE), + hdr.getGcCause()}}; + + String[] infoHeader = {"", ""}; + snapShotInfoModel.setDataVector(infoData, infoHeader); + } + + /** + * Draw the large object heap usage pie chart. + * + * @param snapShot SnapShot + * @param elements Objects Data + * @param pieChart ExpansionContractionPanel is to set the chart. + * @param others Other display flag. true is view. + */ + private void drawPieChart(final SnapShot snapShot, final Object[] elements, + final ExpansionContractionPanel pieChart, final boolean others) { + + DefaultPieDataset graphData = new DefaultPieDataset(); + long heapUsage = snapShot.getHeapUsage(); + for (int i = 0; (i < elements.length) && (i < GuiCommon.getRankLevel()); i++) { + ObjectData odata = (ObjectData) elements[i]; + graphData.setValue(new MapKey(odata), odata.getTotalSize()); + heapUsage -= odata.getTotalSize(); + } + + if (others) { + graphData.setValue(new MapKey(0, "Others"), heapUsage); + } + + JFreeChart chart = ChartFactory.createPieChart("", graphData, false, + true, true); + chart.setBackgroundPaint(Color.WHITE); + PiePlot plot = (PiePlot) chart.getPlot(); + plot.setBackgroundPaint(new Color(GuiCommon.getBgColor())); + plot.setLabelGenerator(null); + GraphColorHelper.adjustColor(graphData, plot); + + ChartPanel chartPanel = new ChartPanel(chart); + pieChart.setComponent(chartPanel, true); + } + + /** + * Gets the main components that you want to SnapShotDialog. + * + * @return Main component + */ + public final Box getComp() { + return comp; + } + + /** + * Sets the main components that you want to SnapShotDialog. + * + * @param value Box + */ + public final void setComp(final Box value) { + comp = value; + add(comp); + } + + /** + * The main component to be added to the specified component. + * + * @param value Component + */ + private void addComp(final Component value) { + comp.add(Box.createVerticalStrut(GuiCommon.BORDER_SIZE)); + comp.add(value); + comp.revalidate(); + } +}