2 * Copyright 2000-2010 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.intellij.execution;
19 import com.google.common.collect.Lists;
20 import com.intellij.execution.executors.DefaultRunExecutor;
21 import com.intellij.execution.process.OSProcessHandler;
22 import com.intellij.execution.process.ProcessHandler;
23 import com.intellij.execution.ui.RunContentDescriptor;
24 import com.intellij.execution.ui.RunContentManagerImpl;
25 import com.intellij.ide.errorTreeView.NewErrorTreeViewPanel;
26 import com.intellij.ide.ui.ListCellRendererWrapper;
27 import com.intellij.openapi.application.ApplicationManager;
28 import com.intellij.openapi.command.CommandProcessor;
29 import com.intellij.openapi.components.ServiceManager;
30 import com.intellij.openapi.diagnostic.Logger;
31 import com.intellij.openapi.editor.Editor;
32 import com.intellij.openapi.progress.ProgressIndicator;
33 import com.intellij.openapi.progress.ProgressManager;
34 import com.intellij.openapi.progress.Task;
35 import com.intellij.openapi.project.Project;
36 import com.intellij.openapi.ui.Messages;
37 import com.intellij.openapi.ui.popup.PopupChooserBuilder;
38 import com.intellij.openapi.util.Disposer;
39 import com.intellij.openapi.util.text.StringUtil;
40 import com.intellij.openapi.vfs.VirtualFile;
41 import com.intellij.openapi.wm.ToolWindow;
42 import com.intellij.openapi.wm.ToolWindowId;
43 import com.intellij.openapi.wm.ToolWindowManager;
44 import com.intellij.ui.components.JBList;
45 import com.intellij.ui.content.Content;
46 import com.intellij.ui.content.ContentFactory;
47 import com.intellij.ui.content.MessageView;
48 import com.intellij.util.Consumer;
49 import com.intellij.util.Function;
50 import com.intellij.util.NotNullFunction;
51 import com.intellij.util.concurrency.Semaphore;
52 import com.intellij.util.ui.ErrorTreeView;
53 import com.intellij.util.ui.MessageCategory;
54 import org.jetbrains.annotations.NotNull;
55 import org.jetbrains.annotations.Nullable;
58 import java.util.ArrayList;
59 import java.util.Collection;
60 import java.util.Collections;
61 import java.util.List;
64 * Created by IntelliJ IDEA.
66 * @author: Roman Chernyatchik
69 public class ExecutionHelper {
70 private static final Logger LOG = Logger.getInstance(ExecutionHelper.class.getName());
72 private ExecutionHelper() {
75 public static void showErrors(@NotNull final Project myProject,
76 @NotNull final List<Exception> exceptionList,
77 @NotNull final String tabDisplayName,
78 @Nullable final VirtualFile file) {
79 if (ApplicationManager.getApplication().isUnitTestMode() && !exceptionList.isEmpty()) {
80 throw new RuntimeException(exceptionList.get(0));
82 ApplicationManager.getApplication().invokeLater(new Runnable() {
84 if (myProject.isDisposed()) return;
85 if (exceptionList.isEmpty()) {
86 removeContents(null, myProject, tabDisplayName);
90 final RailsErrorViewPanel errorTreeView = new RailsErrorViewPanel(myProject);
92 openMessagesView(errorTreeView, myProject, tabDisplayName);
94 catch (NullPointerException e) {
95 final StringBuilder builder = new StringBuilder();
96 builder.append("Exceptions occured:");
97 for (final Exception exception : exceptionList) {
99 builder.append(exception.getMessage());
101 Messages.showErrorDialog(builder.toString(), "Execution Error");
104 for (final Exception exception : exceptionList) {
105 String[] messages = StringUtil.splitByLines(exception.getMessage());
106 if (messages.length == 0) messages = new String[]{"Unknown Error"};
107 errorTreeView.addMessage(MessageCategory.ERROR, messages, file, -1, -1, null);
110 ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.MESSAGES_WINDOW).activate(null);
115 private static void openMessagesView(@NotNull final RailsErrorViewPanel errorTreeView,
116 @NotNull final Project myProject,
117 @NotNull final String tabDisplayName) {
118 CommandProcessor commandProcessor = CommandProcessor.getInstance();
119 commandProcessor.executeCommand(myProject, new Runnable() {
121 final MessageView messageView = ServiceManager.getService(myProject, MessageView.class);
122 final Content content = ContentFactory.SERVICE.getInstance().createContent(errorTreeView, tabDisplayName, true);
123 messageView.getContentManager().addContent(content);
124 Disposer.register(content, errorTreeView);
125 messageView.getContentManager().setSelectedContent(content);
126 removeContents(content, myProject, tabDisplayName);
128 }, "Open message view", null);
131 private static void removeContents(@Nullable final Content notToRemove,
132 @NotNull final Project myProject,
133 @NotNull final String tabDisplayName) {
134 MessageView messageView = ServiceManager.getService(myProject, MessageView.class);
135 Content[] contents = messageView.getContentManager().getContents();
136 for (Content content : contents) {
137 LOG.assertTrue(content != null);
138 if (content.isPinned()) continue;
139 if (tabDisplayName.equals(content.getDisplayName()) && content != notToRemove) {
140 ErrorTreeView listErrorView = (ErrorTreeView)content.getComponent();
141 if (listErrorView != null) {
142 if (messageView.getContentManager().removeContent(content, true)) {
150 public static Collection<RunContentDescriptor> findRunningConsoleByCmdLine(final Project project,
151 @NotNull final NotNullFunction<String, Boolean> cmdLineMatcher) {
152 return findRunningConsole(project, new NotNullFunction<RunContentDescriptor, Boolean>() {
155 public Boolean fun(RunContentDescriptor selectedContent) {
156 final ProcessHandler processHandler = selectedContent.getProcessHandler();
157 if (processHandler instanceof OSProcessHandler && !processHandler.isProcessTerminated()) {
158 final String commandLine = ((OSProcessHandler)processHandler).getCommandLine();
159 return cmdLineMatcher.fun(commandLine);
166 public static Collection<RunContentDescriptor> findRunningConsoleByTitle(final Project project,
167 @NotNull final NotNullFunction<String, Boolean> titleMatcher) {
168 return findRunningConsole(project, new NotNullFunction<RunContentDescriptor, Boolean>() {
171 public Boolean fun(RunContentDescriptor selectedContent) {
172 return titleMatcher.fun(selectedContent.getDisplayName());
177 public static Collection<RunContentDescriptor> findRunningConsole(final Project project,
178 @NotNull final NotNullFunction<RunContentDescriptor, Boolean> descriptorMatcher) {
179 final ExecutionManager executionManager = ExecutionManager.getInstance(project);
180 final ToolWindow runToolWindow =
181 ToolWindowManager.getInstance(project).getToolWindow(DefaultRunExecutor.getRunExecutorInstance().getId());
182 if (runToolWindow != null && runToolWindow.isVisible()) {
183 final RunContentDescriptor selectedContent = executionManager.getContentManager().getSelectedContent();
184 if (selectedContent != null) {
185 if (descriptorMatcher.fun(selectedContent)) {
186 return Collections.singletonList(selectedContent);
191 final ArrayList<RunContentDescriptor> result = Lists.newArrayList();
192 final RunContentDescriptor[] runContentDescriptors = ((RunContentManagerImpl)executionManager.getContentManager()).getAllDescriptors();
193 for (RunContentDescriptor runContentDescriptor : runContentDescriptors) {
194 if (descriptorMatcher.fun(runContentDescriptor)) {
195 result.add(runContentDescriptor);
201 public static List<RunContentDescriptor> collectConsolesByDisplayName(final Project project,
202 @NotNull NotNullFunction<String, Boolean> titleMatcher) {
203 List<RunContentDescriptor> result = Lists.newArrayList();
204 final ExecutionManager executionManager = ExecutionManager.getInstance(project);
205 final RunContentDescriptor[] runContentDescriptors = ((RunContentManagerImpl)executionManager.getContentManager()).getAllDescriptors();
206 for (RunContentDescriptor runContentDescriptor : runContentDescriptors) {
207 if (titleMatcher.fun(runContentDescriptor.getDisplayName())) {
208 result.add(runContentDescriptor);
214 public static void selectContentDescriptor(final @NotNull Editor editor,
215 @NotNull Collection<RunContentDescriptor> consoles,
216 String selectDialogTitle, final Consumer<RunContentDescriptor> descriptorConsumer) {
217 if (consoles.size() == 1) {
218 RunContentDescriptor descriptor = consoles.iterator().next();
219 descriptorConsumer.consume(descriptor);
220 descriptorToFront(editor, descriptor);
222 else if (consoles.size() > 1) {
223 final JList list = new JBList(consoles);
224 final Icon icon = DefaultRunExecutor.getRunExecutorInstance().getIcon();
225 list.setCellRenderer(new ListCellRendererWrapper<RunContentDescriptor>(list.getCellRenderer()) {
227 public void customize(final JList list,
228 final RunContentDescriptor value,
230 final boolean selected,
231 final boolean hasFocus) {
232 setText(value.getDisplayName());
237 final PopupChooserBuilder builder = new PopupChooserBuilder(list);
238 builder.setTitle(selectDialogTitle);
240 builder.setItemChoosenCallback(new Runnable() {
243 final Object selectedValue = list.getSelectedValue();
244 if (selectedValue instanceof RunContentDescriptor) {
245 RunContentDescriptor descriptor = (RunContentDescriptor)selectedValue;
246 descriptorConsumer.consume(descriptor);
247 descriptorToFront(editor, descriptor);
250 }).createPopup().showInBestPositionFor(editor);
254 private static void descriptorToFront(Editor editor, RunContentDescriptor descriptor) {
255 ExecutionManager.getInstance(editor.getProject()).getContentManager()
256 .toFrontRunContent(DefaultRunExecutor.getRunExecutorInstance(), descriptor);
259 public static class RailsErrorViewPanel extends NewErrorTreeViewPanel {
260 public RailsErrorViewPanel(final Project project) {
261 super(project, "reference.toolWindows.messages");
264 protected boolean canHideWarnings() {
270 public static void executeExternalProcess(@Nullable final Project myProject,
271 @NotNull final OSProcessHandler processHandler,
272 @NotNull final ExecutionMode mode) {
273 final String title = mode.getTitle() != null ? mode.getTitle() : "Please wait...";
274 assert title != null;
276 final Runnable process;
277 if (mode.cancelable()) {
278 process = createCancelableExecutionProcess(processHandler, mode.shouldCancelFun());
281 if (mode.getTimeout() <= 0) {
282 process = new Runnable() {
284 processHandler.waitFor();
289 process = createTimelimitedExecutionProcess(processHandler, mode.getTimeout());
292 if (mode.withModalProgress()) {
293 ProgressManager.getInstance().runProcessWithProgressSynchronously(process, title, mode.cancelable(), myProject,
294 mode.getProgressParentComponent());
296 else if (mode.inBackGround()) {
297 final Task task = new Task.Backgroundable(myProject, title, mode.cancelable()) {
298 public void run(@NotNull final ProgressIndicator indicator) {
302 ProgressManager.getInstance().run(task);
305 final String title2 = mode.getTitle2();
306 final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
307 if (indicator != null && title2 != null) {
308 indicator.setText2(title2);
314 private static Runnable createCancelableExecutionProcess(final ProcessHandler processHandler,
315 final Function<Object, Boolean> cancelableFun) {
316 return new Runnable() {
317 private ProgressIndicator myProgressIndicator;
318 private final Semaphore mySemaphore = new Semaphore();
320 private final Runnable myWaitThread = new Runnable() {
323 processHandler.waitFor();
331 private final Runnable myCancelListener = new Runnable() {
334 if ((myProgressIndicator != null && (myProgressIndicator.isCanceled()
335 || !myProgressIndicator.isRunning()))
336 || (cancelableFun != null && cancelableFun.fun(null).booleanValue())
337 || processHandler.isProcessTerminated()) {
339 if (!processHandler.isProcessTerminated()) {
341 processHandler.destroyProcess();
350 synchronized (this) {
354 catch (InterruptedException e) {
362 myProgressIndicator = ProgressManager.getInstance().getProgressIndicator();
363 if (myProgressIndicator != null && StringUtil.isEmpty(myProgressIndicator.getText())) {
364 myProgressIndicator.setText("Please wait...");
367 LOG.assertTrue(myProgressIndicator != null || cancelableFun != null,
368 "Cancelable process must have an opportunity to be canceled!");
370 ApplicationManager.getApplication().executeOnPooledThread(myWaitThread);
371 ApplicationManager.getApplication().executeOnPooledThread(myCancelListener);
373 mySemaphore.waitFor();
378 private static Runnable createTimelimitedExecutionProcess(final OSProcessHandler processHandler,
380 return new Runnable() {
381 private final Semaphore mySemaphore = new Semaphore();
383 private final Runnable myProcessThread = new Runnable() {
386 final boolean finished = processHandler.waitFor(1000 * timeout);
388 LOG.error("Timeout (" + timeout + " sec) on executing: " + processHandler.getCommandLine());
389 processHandler.destroyProcess();
400 ApplicationManager.getApplication().executeOnPooledThread(myProcessThread);
402 mySemaphore.waitFor();