/*
* Copyright 2003-2012 Yusuke Yamamoto
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package samurai.swing;
import samurai.core.FullThreadDump;
import samurai.core.ThreadDump;
import samurai.core.ThreadDumpExtractor;
import samurai.core.ThreadDumpSequence;
import samurai.core.ThreadStatistic;
import samurai.util.Configuration;
import samurai.util.ConfigurationListener;
import samurai.util.GUIResourceBundle;
import samurai.util.OSDetector;
import samurai.util.Task;
import samurai.web.Constants;
import samurai.web.ProgressListener;
import samurai.web.ThreadFilter;
import samurai.web.VelocityHtmlRenderer;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JEditorPane;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JToggleButton;
import javax.swing.ListCellRenderer;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class ThreadDumpPanel extends LogRenderer implements HyperlinkListener,
ConfigurationListener, ClipBoardOperationListener {
public String config_dumpFontFamily = "Monospace";
public String config_dumpFontSize = "12";
private Properties velocityContext = new Properties();
private JProgressBar progressBar = new JProgressBar();
ImageIcon forwardIcon = new ImageIcon(ThreadDumpPanel.class.getResource("images/forward.gif"));
ImageIcon backwardIcon = new ImageIcon(ThreadDumpPanel.class.getResource("images/backward.gif"));
final public JButton saveButton = new JButton();
public JButton openButton = new JButton();
public JButton trashButton = new JButton();
public JToggleButton tableButton = new JToggleButton();
public JToggleButton fullButton = new JToggleButton();
public JToggleButton sequenceButton = new JToggleButton();
ImageIcon saveButtonIcon = new ImageIcon(ThreadDumpPanel.class.getResource("images/save.gif"));
ImageIcon openButtonIcon;
ImageIcon trashButtonIcon = new ImageIcon(ThreadDumpPanel.class.getResource("images/trash.gif"));
ImageIcon tableIcon = new ImageIcon(ThreadDumpPanel.class.getResource("images/tableButton.gif"));
ImageIcon fullButtonIcon = new ImageIcon(ThreadDumpPanel.class.getResource("images/fullButton.gif"));
ImageIcon sequenceButtonIcon = new ImageIcon(ThreadDumpPanel.class.getResource("images/sequenceButton.gif"));
BorderLayout borderLayout1 = new BorderLayout();
private String referer = null;
JEditorPane threadDumpPanel = new JEditorPane() {
public void paint(Graphics g) {
super.paint(g);
if (referer != null) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
threadDumpPanel.scrollToReference(referer);
referer = null;
}
});
}
}
};
JPanel settingPanel = new JPanel();
private static GUIResourceBundle resources = GUIResourceBundle.getInstance();
private VelocityHtmlRenderer renderer = new VelocityHtmlRenderer("samurai/swing/css.vm");
public boolean config_wrapDump = false;
private final Context context;
public ThreadDumpPanel(SamuraiPanel samuraiPanel, Context context) {
super(true, samuraiPanel);
this.context = context;
try {
jbInit();
} catch (Exception ex) {
ex.printStackTrace();
}
resources.inject(this);
}
void jbInit() throws Exception {
this.setLayout(borderLayout1);
this.setMaximumSize(new Dimension(2147483647, 2147483647));
this.setMinimumSize(new Dimension(0, 0));
this.setPreferredSize(new Dimension(400, 800));
this.setLayout(borderLayout1);
threadDumpPanel.setDoubleBuffered(true);
threadDumpPanel.setEditable(false);
threadDumpPanel.setText(resources.getMessage("ThreadDumpPanel.threadDumpHere"));
threadDumpPanel.setContentType("text/html; charset=charset=UTF-8");
settingPanel.setEnabled(true);
settingPanel.setMaximumSize(new Dimension(2147483647, 40));
settingPanel.setMinimumSize(new Dimension(10, 40));
settingPanel.setPreferredSize(new Dimension(10, 40));
settingPanel.setLayout(gridBagLayout1);
buttonPrevious.setBorderPainted(false);
buttonPrevious.setMaximumSize(new Dimension(20, 20));
buttonPrevious.setMinimumSize(new Dimension(20, 20));
buttonPrevious.setPreferredSize(new Dimension(20, 20));
buttonPrevious.addMouseListener(new RolloverBorder(buttonPrevious));
buttonPrevious.setIcon(backwardIcon);
buttonPrevious.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (Constants.MODE_FULL.equals(filter.getMode())) {
int selected = filter.getFullThreadIndex();
if (selected > 0) {
selected--;
filter.setFullThreadIndex(selected);
}
} else if (Constants.MODE_SEQUENCE.equals(filter.getMode())) {
ThreadDumpSequence[] sequences = statistic.getStackTracesAsArray();
for (int i = 0; i < sequences.length; i++) {
if (sequences[i].getId().equals(filter.getThreadId())) {
if (i != 0) {
filter.setThreadId(sequences[i - 1].getId());
} else {
//looping
filter.setThreadId(sequences[sequences.length - 1].getId());
}
break;
}
}
}
updateHtml();
}
});
buttonNext.setBorderPainted(false);
buttonNext.setMaximumSize(new Dimension(20, 20));
buttonNext.setMinimumSize(new Dimension(20, 20));
buttonNext.setPreferredSize(new Dimension(20, 20));
buttonNext.setIcon(forwardIcon);
buttonNext.addMouseListener(new RolloverBorder(buttonNext));
buttonNext.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (Constants.MODE_FULL.equals(filter.getMode())) {
int selected = filter.getFullThreadIndex();
if (selected < statistic.getFullThreadDumpCount() - 1) {
selected++;
filter.setFullThreadIndex(selected);
}
} else if (Constants.MODE_SEQUENCE.equals(filter.getMode())) {
ThreadDumpSequence[] sequences = statistic.getStackTracesAsArray();
for (int i = 0; i < sequences.length; i++) {
if (sequences[i].getId().equals(filter.getThreadId())) {
if (i != (sequences.length - 1)) {
filter.setThreadId(sequences[i + 1].getId());
} else {
//looping
filter.setThreadId(sequences[0].getId());
}
break;
}
}
}
updateHtml();
}
});
jSplitPane1.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
jSplitPane1.setOneTouchExpandable(true);
jSplitPane1.setMinimumSize(new Dimension(50, 50));
jSplitPane1.setPreferredSize(new Dimension(50, 50));
jSplitPane1.setContinuousLayout(true);
jSplitPane1.setBorder(null);
progressBar.setStringPainted(true);
showThreadList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
// showThreadList.addMouseListener(new
// FullThreadDumpPanel_showThreadList_mouseAdapter(this));
showThreadList.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent event) {
// ( (StackTraces) showThreadList.getSelectedValue()).getId().equals(filter.getThreadId())
// showThreadList.getSelectedIndex()
if (-1 != showThreadList.getSelectedIndex()) {
if (Constants.MODE_FULL.equals(filter.getMode())) {
//ensure that selected thread comes to the top of the pane
// JScrollBar scrollBar = jScrollPane3.getVerticalScrollBar();
// scrollBar.setValue(scrollBar.getMaximum());
threadDumpPanel.scrollToReference(((ThreadDumpSequence) showThreadList.getSelectedValue()).getId());
// context.getSearchPanel().searchNext(threadDumpPanel, ( (StackTraces) showThreadList.getSelectedValue()).getId(), 0);
// threadDumpPanel.grabFocus();
} else if (Constants.MODE_SEQUENCE.equals(filter.getMode())) {
if (!((ThreadDumpSequence) showThreadList.getSelectedValue()).getId().equals(
filter.getThreadId())) {
filter.setThreadId(((ThreadDumpSequence) showThreadList.getSelectedValue()).getId());
updateHtml();
}
} else if (Constants.MODE_TABLE.equals(filter.getMode())) {
filter.setMode(Constants.MODE_SEQUENCE);
filter.setThreadId(((ThreadDumpSequence) showThreadList.getSelectedValue()).getId());
updateHtml();
}
}
}
});
showThreadList.setCellRenderer(new ThreadCellRenderer());
saveButton.setBorderPainted(false);
saveButton.setMaximumSize(new Dimension(20, 20));
saveButton.setMinimumSize(new Dimension(20, 20));
saveButton.setPreferredSize(new Dimension(20, 20));
saveButton.setToolTipText("*ThreadDumpPanel.saveAsHtml*");
saveButton.setFocusPainted(false);
saveButton.setIcon(saveButtonIcon);
saveButton.addActionListener(buttonListener);
saveButton.addMouseListener(new RolloverBorder(saveButton));
if (OSDetector.isMac()) {
openButtonIcon = new ImageIcon(MainFrame.class.getResource("images/folder_mac.gif"));
}
if (OSDetector.isWindows()) {
openButtonIcon = new ImageIcon(MainFrame.class.getResource("images/folder_win.gif"));
}
openButton.setBorderPainted(false);
openButton.setMaximumSize(new Dimension(20, 20));
openButton.setMinimumSize(new Dimension(20, 20));
openButton.setPreferredSize(new Dimension(20, 20));
openButton.setToolTipText("*ThreadDumpPanel.openFolder*");
openButton.setFocusPainted(false);
openButton.setIcon(openButtonIcon);
openButton.addActionListener(buttonListener);
openButton.setEnabled(false);
openButton.addMouseListener(new RolloverBorder(openButton));
trashButton.setBorderPainted(false);
trashButton.setMaximumSize(new Dimension(20, 20));
trashButton.setMinimumSize(new Dimension(20, 20));
trashButton.setPreferredSize(new Dimension(20, 20));
trashButton.setToolTipText("*ThreadDumpPanel.clear*");
trashButton.setFocusPainted(false);
trashButton.setIcon(trashButtonIcon);
trashButton.addActionListener(buttonListener);
trashButton.setEnabled(true);
trashButton.addMouseListener(new RolloverBorder(trashButton));
tableButton.setMaximumSize(new Dimension(20, 20));
tableButton.setMinimumSize(new Dimension(20, 20));
tableButton.setPreferredSize(new Dimension(20, 20));
tableButton.setToolTipText("*ThreadDumpPanel.tableView*");
tableButton.setFocusPainted(false);
tableButton.setIcon(tableIcon);
tableButton.addActionListener(buttonListener);
tableButton.setSelected(true);
sequenceButton.setMaximumSize(new Dimension(20, 20));
sequenceButton.setMinimumSize(new Dimension(20, 20));
sequenceButton.setPreferredSize(new Dimension(20, 20));
sequenceButton.setToolTipText("*ThreadDumpPanel.sequenceView*");
sequenceButton.setFocusPainted(false);
sequenceButton.setIcon(sequenceButtonIcon);
sequenceButton.addActionListener(buttonListener);
fullButton.setMaximumSize(new Dimension(20, 20));
fullButton.setMinimumSize(new Dimension(20, 20));
fullButton.setPreferredSize(new Dimension(20, 20));
fullButton.setToolTipText("*ThreadDumpPanel.threadDumpView*");
fullButton.setFocusPainted(false);
fullButton.setIcon(fullButtonIcon);
fullButton.addActionListener(buttonListener);
threadDumpPanel.addHyperlinkListener(this);
threadDumpStatus.setText("");
progressBar.setMaximumSize(new Dimension(80, 20));
progressBar.setPreferredSize(new Dimension(80, 20));
progressBar.setMinimumSize(new Dimension(80, 20));
progressBar.setVisible(false);
this.add(jSplitPane1, BorderLayout.CENTER);
jSplitPane1.add(jScrollPane2, JSplitPane.TOP);
jScrollPane2.getViewport().add(showThreadList, null);
jSplitPane1.add(settingPanel, JSplitPane.RIGHT);
settingPanel.add(jScrollPane3, new GridBagConstraints(0, 0, 10, 1, 1.0, 1.0
, GridBagConstraints.NORTH, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
settingPanel.add(buttonPrevious,
new GridBagConstraints(4, 1, 1, 1, 0.0, 0.0
, GridBagConstraints.CENTER, GridBagConstraints.NONE,
new Insets(0, 5, 0, 0), 0, 0));
settingPanel.add(buttonNext,
new GridBagConstraints(5, 1, 1, 1, 0.0, 0.0
, GridBagConstraints.CENTER, GridBagConstraints.NONE,
new Insets(0, 0, 0, 0), 0, 0));
settingPanel.add(threadDumpStatus, new GridBagConstraints(6, 1, 1, 1, 1.0, 0.0
, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 5, 0, 0), 0, 0));
settingPanel.add(trashButton, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0
, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
settingPanel.add(tableButton, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0
, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 20, 0, 0), 0, 0));
settingPanel.add(fullButton, new GridBagConstraints(2, 1, 1, 1, 0.0, 0.0
, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
settingPanel.add(sequenceButton, new GridBagConstraints(3, 1, 1, 1, 0.0, 0.0
, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 20), 0, 0));
settingPanel.add(progressBar, new GridBagConstraints(7, 1, 1, 1, 0.0, 0.0
, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
settingPanel.add(saveButton, new GridBagConstraints(8, 1, 1, 1, 0.0, 0.0
, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
if (OSDetector.isMac() || OSDetector.isWindows()) {
settingPanel.add(openButton, new GridBagConstraints(9, 1, 1, 1, 0.0, 0.0
, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
}
jScrollPane3.getViewport().add(threadDumpPanel, null);
jSplitPane1.setDividerLocation(200);
}
class RolloverBorder extends MouseAdapter {
private JButton button;
RolloverBorder(JButton button) {
this.button = button;
}
public void mouseEntered(MouseEvent event) {
button.setBorderPainted(button.isEnabled());
}
public void mouseExited(MouseEvent event) {
button.setBorderPainted(false);
}
public void mouseReleased(MouseEvent event) {
button.setBorderPainted(button.isEnabled());
}
}
public static File getTargetDirectory(File file) {
String target = file.getAbsoluteFile().getParent();
String fileName = file.getName();
String directoryName;
if (-1 == fileName.lastIndexOf(".")) {
directoryName = fileName;
} else {
directoryName = fileName.substring(0, fileName.lastIndexOf("."));
}
target = target + File.separator + directoryName;
File targetFile = new File(target);
if (targetFile.exists()) {
int count = 0;
while (targetFile.exists()) {
count++;
targetFile = new File(target + "." + count);
}
}
return targetFile;
}
File savedLocation = null;
JPanel THIS = this;
ActionListener buttonListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
Component source = (Component) e.getSource();
if (source == saveButton) {
if (saveButton.isEnabled()) {
synchronized (saveButton) {
if (saveButton.isEnabled()) {
saveButton.setEnabled(false);
progressBar.setString("");
progressBar.setVisible(true);
context.invokeLater(new Task() {
public void execute() {
VelocityHtmlRenderer renderer = new VelocityHtmlRenderer("samurai/web/outcss.vm", "../images/");
try {
synchronized (statistic) {
savedLocation = getTargetDirectory(currentFile);
renderer.saveTo(statistic, savedLocation, new ProgressListener() {
public void notifyProgress(int finished, int all) {
SwingUtilities.invokeLater(new ProgressTask(finished, all + 9));
}
});
File imageDir = new File(savedLocation.getAbsolutePath() + "/images/");
imageDir.mkdir();
saveStreamAsFile(imageDir, "space.gif");
SwingUtilities.invokeLater(new ProgressTask(progressBar.getMaximum() - 8, progressBar.getMaximum()));
saveStreamAsFile(imageDir, "same-v.gif");
SwingUtilities.invokeLater(new ProgressTask(progressBar.getMaximum() - 7, progressBar.getMaximum()));
saveStreamAsFile(imageDir, "same-h.gif");
SwingUtilities.invokeLater(new ProgressTask(progressBar.getMaximum() - 6, progressBar.getMaximum()));
saveStreamAsFile(imageDir, "deadlocked.gif");
SwingUtilities.invokeLater(new ProgressTask(progressBar.getMaximum() - 5, progressBar.getMaximum()));
saveStreamAsFile(imageDir, "expandable_win.gif");
SwingUtilities.invokeLater(new ProgressTask(progressBar.getMaximum() - 4, progressBar.getMaximum()));
saveStreamAsFile(imageDir, "shrinkable_win.gif");
SwingUtilities.invokeLater(new ProgressTask(progressBar.getMaximum() - 3, progressBar.getMaximum()));
saveStreamAsFile(imageDir, "tableButton.gif");
SwingUtilities.invokeLater(new ProgressTask(progressBar.getMaximum() - 2, progressBar.getMaximum()));
saveStreamAsFile(imageDir, "fullButton.gif");
SwingUtilities.invokeLater(new ProgressTask(progressBar.getMaximum() - 1, progressBar.getMaximum()));
saveStreamAsFile(imageDir, "sequenceButton.gif");
SwingUtilities.invokeLater(new ProgressTask(progressBar.getMaximum(), progressBar.getMaximum()));
}
context.setTemporaryStatus(resources.getMessage("ThreadDumpPanel.saved", savedLocation.getAbsolutePath()));
} catch (Exception ioe) {
ioe.printStackTrace();
SwingUtilities.invokeLater(new ProgressTask(progressBar.getMaximum(), progressBar.getMaximum()));
context.setTemporaryStatus(ioe.getMessage());
}finally{
context.invokeLater(new Task() {
public void execute() {
progressBar.setVisible(false);
progressBar.setValue(0);
saveButton.setEnabled(true);
}
}, 2);
}
}
});
}
}
}
} else if (source == trashButton) {
if (JOptionPane.YES_OPTION ==
JOptionPane.showConfirmDialog(THIS, resources.getMessage("ThreadDumpPanel.confirmClear")
, resources.getMessage("ThreadDumpPanel.clear"), JOptionPane.YES_NO_OPTION)) {
synchronized (statistic) {
init();
}
}
} else if (source == openButton) {
String[] command = null;
if (OSDetector.isMac()) {
command = new String[]{"open", savedLocation.getAbsolutePath()};
} else if (OSDetector.isWindows()) {
command = new String[]{"cmd.exe", "/C", "start", savedLocation.getAbsolutePath()};
}
try {
Runtime.getRuntime().exec(command);
} catch (IOException ioe) {
context.setTemporaryStatus(ioe.getMessage());
}
} else {
JToggleButton button = (JToggleButton) e.getSource();
if (!button.isSelected()) {
button.setSelected(true);
} else {
tableButton.setSelected(tableButton == button ? button.isSelected() :
!button.isSelected());
fullButton.setSelected(fullButton == button ?
button.isSelected() : !button.isSelected());
sequenceButton.setSelected(sequenceButton == button ?
button.isSelected() :
!button.isSelected());
if (tableButton == button) {
filter.setMode(Constants.MODE_TABLE);
} else if (fullButton == button) {
filter.setMode(Constants.MODE_FULL);
} else if (sequenceButton == button) {
filter.setMode(Constants.MODE_SEQUENCE);
}
updateHtml();
}
}
}
};
private void saveStreamAsFile(File parentDir, String fileName) throws IOException {
InputStream is = ThreadDumpPanel.class.getResourceAsStream("/samurai/web/images/" + fileName);
FileOutputStream fos = null;
try {
fos = new FileOutputStream(parentDir.getAbsolutePath() + "/" + fileName);
byte[] buf = new byte[256];
int count;
while (-1 != (count = is.read(buf))) {
fos.write(buf, 0, count);
}
} finally {
if (null != fos) {
try {
fos.close();
} catch (IOException ignore) {
}
}
if (null != is) {
try {
is.close();
} catch (IOException ignore) {
}
}
}
}
class ProgressTask implements Runnable {
int finished, all;
ProgressTask(int finished, int all) {
this.finished = finished;
this.all = all;
}
public void run() {
progressBar.setValue(finished);
progressBar.setMaximum(all);
if (!(finished == all)) {
int progress = finished * 100 / all;
progressBar.setString(progress + "%");
} else {
progressBar.setString("done.");
openButton.setEnabled(true);
}
}
}
private String uri = "";
public void hyperlinkUpdate(HyperlinkEvent e) {
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
uri = e.getDescription();
if (uri.startsWith("#")) {
threadDumpPanel.scrollToReference(e.getDescription().substring(1));
} else {
filter.setQuery(uri);
updateHtml();
}
}
}
GridBagLayout gridBagLayout1 = new GridBagLayout();
JButton buttonPrevious = new JButton();
JButton buttonNext = new JButton();
private ThreadFilter filter = new ThreadFilter();
private ThreadDumpSequence[] threadList = null;
public void changeBunttonFeel() {
invokeLater(new Runnable() {
public void run() {
int selected = filter.getFullThreadIndex();
if (0 == statistic.getFullThreadDumpCount()) {
showThreadList.setEnabled(false);
buttonPrevious.setEnabled(false);
buttonNext.setEnabled(false);
} else {
showThreadList.setEnabled(true);
if (filter.getMode().equals(Constants.MODE_FULL)) {
buttonPrevious.setEnabled(!(selected == 0));
buttonNext.setEnabled(!(statistic.getFullThreadDumpCount() - 1 == selected));
} else {
buttonPrevious.setEnabled(Constants.MODE_SEQUENCE.equals(filter.getMode()));
buttonNext.setEnabled(Constants.MODE_SEQUENCE.equals(filter.getMode()));
}
}
if (null != threadList && threadList.length != 0) {
if (filter.getMode().equals(Constants.MODE_FULL)) {
} else if (filter.getMode().equals(Constants.MODE_SEQUENCE)) {
for (int i = 0; i < threadList.length; i++) {
if (filter.getThreadId().equals(threadList[i].getId())) {
showThreadList.setSelectedIndex(i);
break;
}
}
}
}
if (Constants.MODE_FULL.equals(filter.getMode())) {
showThreadList.setSelectedIndices(new int[0]);
threadDumpStatus.setText(filter.getFullThreadIndex() + 1 + "/" + statistic.getFullThreadDumpCount());
tableButton.setSelected(false);
fullButton.setSelected(true);
sequenceButton.setSelected(false);
} else if (Constants.MODE_TABLE.equals(filter.getMode())) {
showThreadList.setSelectedIndices(new int[0]);
threadDumpStatus.setText("");
tableButton.setSelected(true);
fullButton.setSelected(false);
sequenceButton.setSelected(false);
} else if (Constants.MODE_SEQUENCE.equals(filter.getMode())) {
threadDumpStatus.setText(statistic.getStackTracesById(filter.getThreadId()).getName());
tableButton.setSelected(false);
fullButton.setSelected(false);
sequenceButton.setSelected(true);
}
showThreadList.repaint();
}
}
);
}
private void updateHtml() {
invokeLater(new Runnable() {
public void run() {
synchronized (statistic) {
if (statistic.getFullThreadDumpCount() > 0) {
if ("".equals(filter.getThreadId())) {
filter.setThreadId(statistic.getStackTracesAsArray()[0].getId());
}
threadDumpPanel.setText(renderer.render(filter, statistic, velocityContext));
threadDumpPanel.select(0, 0);
if (-1 != uri.indexOf("#")) {
referer = uri.substring(uri.indexOf("#") + 1);
}
changeBunttonFeel();
for (int i = 0; i < threadList.length; i++) {
if ((threadList[i]).getName().equals(filter.getThreadId())) {
showThreadList.setSelectedIndex(i);
}
}
}
}
}
});
}
final ThreadStatistic statistic = new ThreadStatistic() {
public synchronized void onFullThreadDump(FullThreadDump fullThreadDump) {
super.onFullThreadDump(fullThreadDump);
invokeLater(new Runnable() {
public void run() {
showMe(resources.getMessage("ThreadDumpPanel.threadDump"));
threadList = statistic.getStackTracesAsArray();
showThreadList.setListData(threadList);
showThreadList.clearSelection();
}
});
updateHtml();
}
};
private ThreadDumpExtractor analyzer = new ThreadDumpExtractor(statistic);
JSplitPane jSplitPane1 = new JSplitPane();
JScrollPane jScrollPane2 = new JScrollPane();
JScrollPane jScrollPane3 = new JScrollPane();
JList showThreadList = new JList();
JLabel threadDumpStatus = new JLabel();
File currentFile;
public void onLine(File file, String line, long filePointer) {
super.onLine(file, line, filePointer);
analyzer.analyzeLine(line);
}
public void logStarted(File file, long filePointer) {
super.logStarted(file, filePointer);
currentFile = file;
}
public void logEnded(File file, long filePointer) {
super.logEnded(file, filePointer);
analyzer.finish();
}
public synchronized void clearBuffer(){
init();
analyzer = new ThreadDumpExtractor(statistic);
hideMe();
}
public synchronized void close() {
super.close();
clearBuffer();
}
private void init() {
statistic.reset();
filter.reset();
threadDumpPanel.setText(resources.getMessage(
"ThreadDumpPanel.threadDumpHere"));
changeBunttonFeel();
}
void showThreadList_actionPerformed(ActionEvent e) {
if (showThreadList.getSelectedIndex() == 0) {
filter.setMode(Constants.MODE_FULL);
} else {
filter.setMode(Constants.MODE_SEQUENCE);
filter.setThreadId((String) showThreadList.getSelectedValue());
}
updateHtml();
}
public synchronized void onConfigurationChanged(Configuration config) {
config.apply(renderer);
velocityContext.setProperty("fontFamily", config_dumpFontFamily);
velocityContext.setProperty("fontSize", config_dumpFontSize);
updateHtml();
}
class ThreadCellRenderer extends JLabel implements ListCellRenderer {
public ThreadCellRenderer() {
setOpaque(true);
}
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
ThreadDumpSequence threadDumps = ((ThreadDumpSequence) value);
ThreadDump currentThreadDump = threadDumps.get(filter.getFullThreadIndex());
Color fgColor = Color.BLACK;
setFont(getFont().deriveFont(0));
if (null != currentThreadDump) {
if (Constants.MODE_FULL.equals(filter.getMode())) {
if (currentThreadDump.isIdle()) {
fgColor = Color.GRAY;
} else if (currentThreadDump.isBlocked()) {
fgColor = Color.RED;
}
}
} else {
//no thread in this fullthreaddump
// fgColor = Color.GRAY;
}
setText(value.toString());
setBackground(isSelected ? fgColor : Color.white);
setForeground(isSelected ? Color.white : fgColor);
return this;
}
}
public void cut() {
}
public void copy() {
this.threadDumpPanel.copy();
}
public void paste() {
}
}