diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/ExportThreadsAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/ExportThreadsAction.java index ed829100c502..25d95ed86292 100644 --- a/java/debugger/impl/src/com/intellij/debugger/actions/ExportThreadsAction.java +++ b/java/debugger/impl/src/com/intellij/debugger/actions/ExportThreadsAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -21,61 +21,49 @@ package com.intellij.debugger.actions; import com.intellij.debugger.DebuggerManagerEx; +import com.intellij.debugger.engine.DebugProcessImpl; +import com.intellij.debugger.engine.events.DebuggerCommandImpl; import com.intellij.debugger.impl.DebuggerContextImpl; import com.intellij.debugger.impl.DebuggerSession; -import com.intellij.debugger.ui.ExportDialog; -import com.intellij.idea.ActionsBundle; +import com.intellij.ide.actions.ExportToTextFileAction; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.Presentation; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.SystemProperties; +import com.intellij.unscramble.ThreadDumpPanel; +import com.intellij.unscramble.ThreadState; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; +import java.util.List; public class ExportThreadsAction extends AnAction implements AnAction.TransparentUpdate { public void actionPerformed(AnActionEvent e) { - Project project = CommonDataKeys.PROJECT.getData(e.getDataContext()); + final Project project = CommonDataKeys.PROJECT.getData(e.getDataContext()); if (project == null) { return; } DebuggerContextImpl context = (DebuggerManagerEx.getInstanceEx(project)).getContext(); - if(context.getDebuggerSession() != null) { - String destinationDirectory = ""; - final VirtualFile baseDir = project.getBaseDir(); - if (baseDir != null) destinationDirectory = baseDir.getPresentableUrl(); - - ExportDialog dialog = new ExportDialog(context.getDebugProcess(), destinationDirectory); - if (dialog.showAndGet()) { - try { - File file = new File(dialog.getFilePath()); - BufferedWriter writer = new BufferedWriter(new FileWriter(file)); - try { - String text = StringUtil.convertLineSeparators(dialog.getTextToSave(), SystemProperties.getLineSeparator()); - writer.write(text); + final DebuggerSession session = context.getDebuggerSession(); + if(session != null && session.isAttached()) { + final DebugProcessImpl process = context.getDebugProcess(); + if (process != null) { + process.getManagerThread().invoke(new DebuggerCommandImpl() { + protected void action() throws Exception { + final List threads = ThreadDumpAction.buildThreadStates(process.getVirtualMachineProxy()); + ApplicationManager.getApplication().invokeLater(new Runnable() { + public void run() { + ExportToTextFileAction.export(project, ThreadDumpPanel.createToFileExporter(project, threads)); + } + }, ModalityState.NON_MODAL); } - finally { - writer.close(); - } - } - catch (IOException ex) { - Messages - .showMessageDialog(project, ex.getMessage(), ActionsBundle.actionText(DebuggerActions.EXPORT_THREADS), Messages.getErrorIcon()); - } + }); } } } - - public void update(AnActionEvent event){ Presentation presentation = event.getPresentation(); Project project = CommonDataKeys.PROJECT.getData(event.getDataContext()); diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/ThreadDumpAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/ThreadDumpAction.java index e8eb1a902504..96e6d015f026 100644 --- a/java/debugger/impl/src/com/intellij/debugger/actions/ThreadDumpAction.java +++ b/java/debugger/impl/src/com/intellij/debugger/actions/ThreadDumpAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -83,7 +83,7 @@ public class ThreadDumpAction extends AnAction implements AnAction.TransparentUp } } - private static List buildThreadStates(VirtualMachineProxyImpl vmProxy) { + static List buildThreadStates(VirtualMachineProxyImpl vmProxy) { final List threads = vmProxy.getVirtualMachine().allThreads(); final List result = new ArrayList(); final Map nameToThreadMap = new HashMap(); diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebugProcess.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebugProcess.java index 09898a068e3a..0b1cd18bb05b 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebugProcess.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebugProcess.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -322,7 +322,7 @@ public class JavaDebugProcess extends XDebugProcess { public void registerAdditionalActions(@NotNull DefaultActionGroup leftToolbar, @NotNull DefaultActionGroup topToolbar, @NotNull DefaultActionGroup settings) { Constraints beforeRunner = new Constraints(Anchor.BEFORE, "Runner.Layout"); leftToolbar.add(Separator.getInstance(), beforeRunner); - leftToolbar.add(ActionManager.getInstance().getAction(DebuggerActions.EXPORT_THREADS), beforeRunner); + //leftToolbar.add(ActionManager.getInstance().getAction(DebuggerActions.EXPORT_THREADS), beforeRunner); leftToolbar.add(ActionManager.getInstance().getAction(DebuggerActions.DUMP_THREADS), beforeRunner); leftToolbar.add(Separator.getInstance(), beforeRunner); diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerSessionTab.java b/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerSessionTab.java index 8e5cfb72ce3f..a088e953557f 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerSessionTab.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerSessionTab.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -287,7 +287,7 @@ public class DebuggerSessionTab extends DebuggerSessionTabBase implements Dispos } leftToolbar.addSeparator(); - addAction(leftToolbar, DebuggerActions.EXPORT_THREADS); + //addAction(leftToolbar, DebuggerActions.EXPORT_THREADS); addAction(leftToolbar, DebuggerActions.DUMP_THREADS); leftToolbar.addSeparator(); diff --git a/java/java-impl/src/com/intellij/unscramble/ThreadDumpPanel.java b/java/java-impl/src/com/intellij/unscramble/ThreadDumpPanel.java index 1c37445ba749..f477247181c0 100644 --- a/java/java-impl/src/com/intellij/unscramble/ThreadDumpPanel.java +++ b/java/java-impl/src/com/intellij/unscramble/ThreadDumpPanel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -19,6 +19,7 @@ import com.intellij.codeInsight.highlighting.HighlightManager; import com.intellij.execution.ui.ConsoleView; import com.intellij.icons.AllIcons; import com.intellij.ide.DataManager; +import com.intellij.ide.ExporterToTextFile; import com.intellij.notification.NotificationGroup; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.editor.Editor; @@ -32,22 +33,25 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.ui.Splitter; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.openapi.wm.ToolWindowId; import com.intellij.ui.*; import com.intellij.ui.components.JBList; import com.intellij.util.PlatformIcons; import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.Nullable; import javax.swing.*; +import javax.swing.event.ChangeListener; import javax.swing.event.DocumentEvent; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import java.awt.*; import java.awt.datatransfer.StringSelection; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; +import java.io.File; +import java.util.*; import java.util.List; import static com.intellij.icons.AllIcons.Debugger.ThreadStates.*; @@ -56,7 +60,7 @@ import static com.intellij.icons.AllIcons.Debugger.ThreadStates.*; * @author Jeka * @author Konstantin Bulenkov */ -public class ThreadDumpPanel extends JPanel { +public class ThreadDumpPanel extends JPanel implements DataProvider { private static final Icon PAUSE_ICON_DAEMON = new LayeredIcon(Paused, Daemon_sign); private static final Icon LOCKED_ICON_DAEMON = new LayeredIcon(Locked, Daemon_sign); private static final Icon RUNNING_ICON_DAEMON = new LayeredIcon(Running, Daemon_sign); @@ -68,6 +72,7 @@ public class ThreadDumpPanel extends JPanel { private final List myThreadDump; private final JPanel myFilterPanel; private final SearchTextField myFilterField; + private final ExporterToTextFile myExporterToTextFile; public ThreadDumpPanel(final Project project, final ConsoleView consoleView, final DefaultActionGroup toolbarActions, final List threadDump) { super(new BorderLayout()); @@ -103,11 +108,14 @@ public class ThreadDumpPanel extends JPanel { } }); + myExporterToTextFile = createToFileExporter(project, myThreadDump); + FilterAction filterAction = new FilterAction(); filterAction.registerCustomShortcutSet(ActionManager.getInstance().getAction(IdeActions.ACTION_FIND).getShortcutSet(), myThreadList); toolbarActions.add(filterAction); toolbarActions.add(new CopyToClipboardAction(threadDump, project)); toolbarActions.add(new SortThreadsAction()); + toolbarActions.add(ActionManager.getInstance().getAction(IdeActions.ACTION_EXPORT_TO_TEXT_FILE)); add(ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, toolbarActions, false).getComponent(), BorderLayout.WEST); JPanel leftPanel = new JPanel(new BorderLayout()); @@ -137,6 +145,15 @@ public class ThreadDumpPanel extends JPanel { } } + @Nullable + @Override + public Object getData(@NonNls String dataId) { + if (PlatformDataKeys.EXPORTER_TO_TEXT_FILE.is(dataId)) { + return myExporterToTextFile; + } + return null; + } + private void updateThreadList() { String text = myFilterPanel.isVisible() ? myFilterField.getText() : ""; DefaultListModel model = (DefaultListModel)myThreadList.getModel(); @@ -354,4 +371,59 @@ public class ThreadDumpPanel extends JPanel { updateThreadList(); } } + + public static ExporterToTextFile createToFileExporter(Project project, List threadStates) { + return new MyToFileExporter(project, threadStates); + } + + private static class MyToFileExporter implements ExporterToTextFile { + private final Project myProject; + private final List myThreadStates; + + public MyToFileExporter(Project project, List threadStates) { + myProject = project; + myThreadStates = threadStates; + } + + @Override + public JComponent getSettingsEditor() { + return null; + } + + @Override + public void addSettingsChangedListener(ChangeListener listener) throws TooManyListenersException {} + + @Override + public void removeSettingsChangedListener(ChangeListener listener) {} + + @Override + public String getReportText() { + StringBuilder sb = new StringBuilder(); + for (ThreadState state : myThreadStates) { + sb.append(state.getStackTrace()).append("\n\n"); + } + return sb.toString(); + } + + private static final @NonNls String DEFAULT_REPORT_FILE_NAME = "threads_report.txt"; + + @Override + public String getDefaultFilePath() { + final VirtualFile baseDir = myProject.getBaseDir(); + if (baseDir != null) { + return baseDir.getPresentableUrl() + File.separator + DEFAULT_REPORT_FILE_NAME; + } + return null; + } + + @Override + public void exportedTo(String filePath) { + + } + + @Override + public boolean canExport() { + return !myThreadStates.isEmpty(); + } + } } diff --git a/resources/src/idea/JavaActions.xml b/resources/src/idea/JavaActions.xml index c58747a57d3f..9efac63d0dce 100644 --- a/resources/src/idea/JavaActions.xml +++ b/resources/src/idea/JavaActions.xml @@ -127,7 +127,7 @@ - +