fix for output file by short name inside working dir (IDEA-153832)
[idea/community.git] / platform / lang-impl / src / com / intellij / diagnostic / logging / OutputFileUtil.java
1 /*
2  * Copyright 2000-2011 JetBrains s.r.o.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 package com.intellij.diagnostic.logging;
17
18 import com.intellij.execution.CommonProgramRunConfigurationParameters;
19 import com.intellij.execution.configurations.RunConfigurationBase;
20 import com.intellij.execution.filters.Filter;
21 import com.intellij.execution.filters.HyperlinkInfo;
22 import com.intellij.execution.process.ProcessAdapter;
23 import com.intellij.execution.process.ProcessEvent;
24 import com.intellij.execution.process.ProcessHandler;
25 import com.intellij.execution.process.ProcessOutputTypes;
26 import com.intellij.execution.ui.ConsoleView;
27 import com.intellij.execution.ui.ExecutionConsole;
28 import com.intellij.openapi.application.ApplicationManager;
29 import com.intellij.openapi.fileEditor.FileEditorManager;
30 import com.intellij.openapi.fileEditor.OpenFileDescriptor;
31 import com.intellij.openapi.project.Project;
32 import com.intellij.openapi.util.Computable;
33 import com.intellij.openapi.util.Key;
34 import com.intellij.openapi.util.io.FileUtil;
35 import com.intellij.openapi.util.text.StringUtil;
36 import com.intellij.openapi.vfs.LocalFileSystem;
37 import com.intellij.openapi.vfs.VirtualFile;
38 import org.jetbrains.annotations.NotNull;
39 import org.jetbrains.annotations.Nullable;
40
41 import java.io.File;
42 import java.io.FileNotFoundException;
43 import java.io.FileOutputStream;
44 import java.io.PrintStream;
45
46 /**
47  * User: anna
48  * Date: 10/20/11
49  */
50 public class OutputFileUtil {
51   private static final String CONSOLE_OUTPUT_FILE_MESSAGE = "Console output is saving to: ";
52
53   private OutputFileUtil() {
54   }
55
56   public static File getOutputFile(@NotNull final RunConfigurationBase configuration) {
57     String outputFilePath = configuration.getOutputFilePath();
58     if (outputFilePath != null) {
59       final String filePath = FileUtil.toSystemDependentName(outputFilePath);
60       File file = new File(filePath);
61       if (configuration instanceof CommonProgramRunConfigurationParameters && !FileUtil.isAbsolute(filePath)) {
62         String directory = ((CommonProgramRunConfigurationParameters)configuration).getWorkingDirectory();
63         if (directory != null) {
64           file = new File(new File(directory), filePath);
65         }
66       }
67       return file;
68     }
69     return null;
70   }
71
72   public static void attachDumpListener(@NotNull final RunConfigurationBase configuration, @NotNull final ProcessHandler startedProcess, @Nullable final ExecutionConsole console) {
73     if (!configuration.isSaveOutputToFile()) {
74       return;
75     }
76
77     final File file = getOutputFile(configuration);
78     if (file != null) {
79       startedProcess.addProcessListener(new ProcessAdapter() {
80         private PrintStream myOutput;
81         @Override
82         public void onTextAvailable(ProcessEvent event, Key outputType) {
83           if (configuration.collectOutputFromProcessHandler() && myOutput != null && outputType != ProcessOutputTypes.SYSTEM) {
84             myOutput.print(event.getText());
85           }
86         }
87
88         @Override
89         public void startNotified(ProcessEvent event) {
90           try {
91             myOutput = new PrintStream(new FileOutputStream(file));
92           }
93           catch (FileNotFoundException ignored) {
94           }
95           startedProcess.notifyTextAvailable(CONSOLE_OUTPUT_FILE_MESSAGE + FileUtil.toSystemDependentName(file.getAbsolutePath()) + "\n", ProcessOutputTypes.SYSTEM);
96         }
97
98         @Override
99         public void processTerminated(ProcessEvent event) {
100           startedProcess.removeProcessListener(this);
101           if (myOutput != null) {
102             myOutput.close();
103           }
104         }
105       });
106       if (console instanceof ConsoleView) {
107         ((ConsoleView)console).addMessageFilter(new ShowOutputFileFilter());
108       }
109     }
110   }
111
112   private static class ShowOutputFileFilter implements Filter {
113     @Override
114     public Result applyFilter(String line, int entireLength) {
115       if (line.startsWith(CONSOLE_OUTPUT_FILE_MESSAGE)) {
116         final String filePath = StringUtil.trimEnd(line.substring(CONSOLE_OUTPUT_FILE_MESSAGE.length()), "\n");
117
118         return new Result(entireLength - filePath.length() - 1, entireLength, new HyperlinkInfo() {
119           @Override
120           public void navigate(final Project project) {
121             final VirtualFile file =
122               ApplicationManager.getApplication().runWriteAction(new Computable<VirtualFile>() {
123                 @Nullable
124                 @Override
125                 public VirtualFile compute() {
126                   return LocalFileSystem.getInstance().refreshAndFindFileByPath(FileUtil.toSystemIndependentName(filePath));
127                 }
128               });
129
130             if (file != null) {
131               file.refresh(false, false);
132               ApplicationManager.getApplication().runReadAction(new Runnable() {
133                 @Override
134                 public void run() {
135                   FileEditorManager.getInstance(project).openTextEditor(new OpenFileDescriptor(project, file), true);
136                 }
137               });
138             }
139           }
140         });
141       }
142       return null;
143     }
144   }
145 }