Java tutorial
/* * Copyright 2000-2009 JetBrains s.r.o. * * 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. */ /** * created at Dec 14, 2001 * @author Jeka */ package com.intellij.debugger.ui; import com.intellij.debugger.DebuggerBundle; import com.intellij.debugger.DebuggerInvocationUtil; import com.intellij.debugger.HelpID; import com.intellij.debugger.actions.ThreadDumpAction; import com.intellij.debugger.engine.DebugProcessImpl; import com.intellij.debugger.engine.events.DebuggerCommandImpl; import com.intellij.debugger.impl.DebuggerUtilsEx; import com.intellij.debugger.jdi.VirtualMachineProxyImpl; import com.intellij.debugger.ui.impl.watch.MessageDescriptor; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; import com.intellij.openapi.help.HelpManager; import com.intellij.openapi.ide.CopyPasteManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.ScrollPaneFactory; import consulo.internal.com.sun.jdi.*; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; import java.awt.datatransfer.StringSelection; import java.awt.event.ActionEvent; import java.io.File; import java.util.List; public class ExportDialog extends DialogWrapper { private final JTextArea myTextArea = new JTextArea(); private TextFieldWithBrowseButton myTfFilePath; private final Project myProject; private final DebugProcessImpl myDebugProcess; private final CopyToClipboardAction myCopyToClipboardAction = new CopyToClipboardAction(); private static final @NonNls String DEFAULT_REPORT_FILE_NAME = "threads_report.txt"; public ExportDialog(DebugProcessImpl debugProcess, String destinationDirectory) { super(debugProcess.getProject(), true); myDebugProcess = debugProcess; myProject = debugProcess.getProject(); setTitle(DebuggerBundle.message("threads.export.dialog.title")); setOKButtonText(DebuggerBundle.message("button.save")); init(); setOKActionEnabled(false); myCopyToClipboardAction.setEnabled(false); myTextArea.setText(MessageDescriptor.EVALUATING.getLabel()); debugProcess.getManagerThread().invoke(new ExportThreadsCommand( ApplicationManager.getApplication().getModalityStateForComponent(myTextArea))); myTfFilePath.setText(destinationDirectory + File.separator + DEFAULT_REPORT_FILE_NAME); setHorizontalStretch(1.5f); } @NotNull protected Action[] createActions() { return new Action[] { getOKAction(), myCopyToClipboardAction, getCancelAction(), getHelpAction() }; } protected void doHelpAction() { HelpManager.getInstance().invokeHelp(HelpID.EXPORT_THREADS); } protected JComponent createNorthPanel() { JPanel box = new JPanel(new BorderLayout()); box.add(new JLabel(DebuggerBundle.message("label.threads.export.dialog.file")), BorderLayout.WEST); myTfFilePath = new TextFieldWithBrowseButton(); myTfFilePath.addBrowseFolderListener(null, null, myProject, FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor()); box.add(myTfFilePath, BorderLayout.CENTER); JPanel panel = new JPanel(new BorderLayout()); panel.add(box, BorderLayout.CENTER); panel.add(Box.createVerticalStrut(7), BorderLayout.SOUTH); return panel; } protected JComponent createCenterPanel() { myTextArea.setEditable(false); JScrollPane pane = ScrollPaneFactory.createScrollPane(myTextArea); pane.setPreferredSize(new Dimension(400, 300)); return pane; } protected void doOKAction() { String path = myTfFilePath.getText(); File file = new File(path); if (file.isDirectory()) { Messages.showMessageDialog(myProject, DebuggerBundle.message("error.threads.export.dialog.file.is.directory"), DebuggerBundle.message("threads.export.dialog.title"), Messages.getErrorIcon()); } else if (file.exists()) { int answer = Messages.showYesNoDialog(myProject, DebuggerBundle.message("error.threads.export.dialog.file.already.exists", path), DebuggerBundle.message("threads.export.dialog.title"), Messages.getQuestionIcon()); if (answer == 0) { super.doOKAction(); } } else { super.doOKAction(); } } public String getFilePath() { return myTfFilePath.getText(); } public String getTextToSave() { return myTextArea.getText(); } protected String getDimensionServiceKey() { return "#com.intellij.debugger.ui.ExportDialog"; } public static String getExportThreadsText(VirtualMachineProxyImpl vmProxy) { final StringBuffer buffer = new StringBuffer(512); List<ThreadReference> threads = vmProxy.getVirtualMachine().allThreads(); for (ThreadReference threadReference : threads) { final String name = threadName(threadReference); if (name == null) { continue; } buffer.append(name); ReferenceType referenceType = threadReference.referenceType(); if (referenceType != null) { //noinspection HardCodedStringLiteral Field daemon = referenceType.fieldByName("daemon"); if (daemon != null) { Value value = threadReference.getValue(daemon); if (value instanceof BooleanValue && ((BooleanValue) value).booleanValue()) { buffer.append(" ").append(DebuggerBundle.message("threads.export.attribute.label.daemon")); } } //noinspection HardCodedStringLiteral Field priority = referenceType.fieldByName("priority"); if (priority != null) { Value value = threadReference.getValue(priority); if (value instanceof IntegerValue) { buffer.append(", ").append(DebuggerBundle.message("threads.export.attribute.label.priority", ((IntegerValue) value).intValue())); } } } ThreadGroupReference groupReference = threadReference.threadGroup(); if (groupReference != null) { buffer.append(", ").append( DebuggerBundle.message("threads.export.attribute.label.group", groupReference.name())); } buffer.append(", ").append(DebuggerBundle.message("threads.export.attribute.label.status", DebuggerUtilsEx.getThreadStatusText(threadReference.status()))); try { if (vmProxy.canGetOwnedMonitorInfo() && vmProxy.canGetMonitorInfo()) { List<ObjectReference> list = threadReference.ownedMonitors(); for (ObjectReference reference : list) { final List<ThreadReference> waiting = reference.waitingThreads(); for (ThreadReference thread : waiting) { final String waitingThreadName = threadName(thread); if (waitingThreadName != null) { buffer.append("\n\t ").append(DebuggerBundle.message( "threads.export.attribute.label.blocks.thread", waitingThreadName)); } } } } ObjectReference waitedMonitor = vmProxy.canGetCurrentContendedMonitor() ? threadReference.currentContendedMonitor() : null; if (waitedMonitor != null) { if (vmProxy.canGetMonitorInfo()) { ThreadReference waitedThread = waitedMonitor.owningThread(); if (waitedThread != null) { final String waitedThreadName = threadName(waitedThread); if (waitedThreadName != null) { buffer.append("\n\t ") .append(DebuggerBundle.message( "threads.export.attribute.label.waiting.for.thread", waitedThreadName, ThreadDumpAction.renderObject(waitedMonitor))); } } } } final List<StackFrame> frames = threadReference.frames(); for (StackFrame stackFrame : frames) { final Location location = stackFrame.location(); buffer.append("\n\t ").append(renderLocation(location)); } } catch (IncompatibleThreadStateException e) { buffer.append("\n\t ") .append(DebuggerBundle.message("threads.export.attribute.error.incompatible.state")); } buffer.append("\n\n"); } return buffer.toString(); } private static String renderLocation(final Location location) { String sourceName; try { sourceName = location.sourceName(); } catch (AbsentInformationException e) { sourceName = "Unknown Source"; } return DebuggerBundle.message("export.threads.stackframe.format", location.declaringType().name() + "." + location.method().name(), sourceName, location.lineNumber()); } private static String threadName(ThreadReference threadReference) { try { return threadReference.name() + "@" + threadReference.uniqueID(); } catch (ObjectCollectedException e) { return null; } } private class CopyToClipboardAction extends AbstractAction { public CopyToClipboardAction() { super(DebuggerBundle.message("button.copy")); putValue(Action.SHORT_DESCRIPTION, DebuggerBundle.message("export.dialog.copy.action.description")); } public void actionPerformed(ActionEvent e) { String s = StringUtil.convertLineSeparators(myTextArea.getText()); CopyPasteManager.getInstance().setContents(new StringSelection(s)); } } private class ExportThreadsCommand extends DebuggerCommandImpl { protected ModalityState myModalityState; public ExportThreadsCommand(ModalityState modalityState) { myModalityState = modalityState; } private void setText(final String text) { DebuggerInvocationUtil.invokeLater(myProject, new Runnable() { public void run() { myTextArea.setText(text); setOKActionEnabled(true); myCopyToClipboardAction.setEnabled(true); } }, myModalityState); } protected void action() { setText(getExportThreadsText(myDebugProcess.getVirtualMachineProxy())); } } }