/*
* Copyright 2013-2016 consulo.io
*
* 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 consulo.backgroundTaskByVfsChange;
import com.intellij.application.options.ReplacePathToMacroMap;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.RunContentExecutor;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.process.CapturingProcessHandler;
import com.intellij.execution.process.ProcessAdapter;
import com.intellij.execution.process.ProcessEvent;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.components.ExpandMacroToPathMap;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.pointers.VirtualFilePointer;
import com.intellij.openapi.vfs.pointers.VirtualFilePointerManager;
import com.intellij.tools.ToolProcessAdapter;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ui.UIUtil;
import consulo.annotations.RequiredReadAction;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* @author VISTALL
* @since 23:16/06.10.13
*/
public class BackgroundTaskByVfsChangeTaskImpl implements BackgroundTaskByVfsChangeTask {
public static final Logger LOGGER = Logger.getInstance(BackgroundTaskByVfsChangeTaskImpl.class);
private final Project myProject;
private final BackgroundTaskByVfsParameters myParameters;
private final VirtualFilePointer myVirtualFilePointer;
private final String myProviderName;
private final String myName;
private boolean myEnabled;
private final BackgroundTaskByVfsChangeProvider myProvider;
private final BackgroundTaskByVfsChangeManagerImpl myManager;
private String[] myGeneratedFilePaths;
public BackgroundTaskByVfsChangeTaskImpl(@NotNull Project project,
@NotNull VirtualFilePointer pointer,
@NotNull BackgroundTaskByVfsParameters parameters,
@NotNull String providerName,
@NotNull String name,
@Nullable BackgroundTaskByVfsChangeProvider provider,
@NotNull BackgroundTaskByVfsChangeManagerImpl manager) {
myProject = project;
myParameters = parameters;
myVirtualFilePointer = pointer;
myProviderName = providerName;
myName = name;
myProvider = provider;
myManager = manager;
}
public BackgroundTaskByVfsChangeTaskImpl(@NotNull Project project,
@NotNull VirtualFile virtualFile,
@NotNull BackgroundTaskByVfsChangeManagerImpl manager,
@NotNull BackgroundTaskByVfsChangeProvider provider,
@NotNull String name,
@NotNull BackgroundTaskByVfsParameters parameters) {
this(project, VirtualFilePointerManager.getInstance().create(virtualFile, manager, null), parameters, provider.getTemplateName(), name, provider, manager);
}
public BackgroundTaskByVfsChangeTaskImpl(@NotNull Project project,
@NotNull VirtualFilePointer pointer,
@NotNull String provider,
@NotNull String name,
@NotNull BackgroundTaskByVfsParameters parameters,
@NotNull BackgroundTaskByVfsChangeManagerImpl manager) {
this(project, pointer, parameters, provider, name, findProviderByName(provider), manager);
}
@Nullable
private static BackgroundTaskByVfsChangeProvider findProviderByName(String name) {
BackgroundTaskByVfsChangeProvider temp = null;
for (BackgroundTaskByVfsChangeProvider backgroundTaskByVfsChangeProvider : BackgroundTaskByVfsChangeProvider.EP_NAME.getExtensions()) {
if (Comparing.equal(name, backgroundTaskByVfsChangeProvider.getTemplateName())) {
temp = backgroundTaskByVfsChangeProvider;
break;
}
}
return temp;
}
public void run(@NotNull final ActionCallback actionCallback) {
try {
final ExpandMacroToPathMap expandMacroToPathMap = createExpandMacroToPathMap();
GeneralCommandLine commandLine = new GeneralCommandLine();
commandLine.setExePath(myParameters.getExePath());
String programParameters = myParameters.getProgramParameters();
if (programParameters != null) {
commandLine.addParameters(StringUtil.split(expandMacroToPathMap.substitute(programParameters, false), " "));
}
commandLine.setWorkDirectory(expandMacroToPathMap.substitute(myParameters.getWorkingDirectory(), false));
commandLine.setPassParentEnvironment(myParameters.isPassParentEnvs());
commandLine.getEnvironment().putAll(myParameters.getEnvs());
CapturingProcessHandler processHandler = new CapturingProcessHandler(commandLine);
processHandler.addProcessListener(new ProcessAdapter() {
@Override
public void processTerminated(ProcessEvent event) {
actionCallback.setDone();
String outPath = myParameters.getOutPath();
if (outPath == null) {
return;
}
String substitute = expandMacroToPathMap.substitute(outPath, false);
final VirtualFile fileByPath = LocalFileSystem.getInstance().findFileByPath(substitute);
if (fileByPath != null) {
new WriteAction<Object>() {
@Override
protected void run(Result<Object> result) throws Throwable {
fileByPath.refresh(false, true);
}
}.execute();
}
}
});
if (myParameters.isShowConsole()) {
final RunContentExecutor contentExecutor = new RunContentExecutor(myProject, processHandler).withTitle(myProviderName).withActivateToolWindow(false);
UIUtil.invokeLaterIfNeeded(contentExecutor::run);
}
else {
processHandler.addProcessListener(new ToolProcessAdapter(myProject, true, myName));
processHandler.startNotify();
}
}
catch (ExecutionException e) {
actionCallback.setRejected();
LOGGER.error(e);
}
}
public ExpandMacroToPathMap createExpandMacroToPathMap() {
final ExpandMacroToPathMap expandMacroToPathMap = new ExpandMacroToPathMap();
expandMacroToPathMap.addMacroExpand("FileName", myVirtualFilePointer.getFileName());
expandMacroToPathMap.addMacroExpand("FilePath", myVirtualFilePointer.getPresentableUrl());
File parentFile = FileUtilRt.getParentFile(new File(myVirtualFilePointer.getPresentableUrl()));
expandMacroToPathMap.addMacroExpand("FileParentPath", parentFile.getAbsolutePath());
return expandMacroToPathMap;
}
private ExpandMacroToPathMap createExpandOutMacroToPathMap() {
final ExpandMacroToPathMap expandMacroToPathMap = new ExpandMacroToPathMap();
expandMacroToPathMap.addMacroExpand("FileName", myVirtualFilePointer.getFileName());
expandMacroToPathMap.addMacroExpand("FilePath", myVirtualFilePointer.getPresentableUrl());
expandMacroToPathMap.addMacroExpand("OutPath", myParameters.getOutPath());
File parentFile = FileUtilRt.getParentFile(new File(myVirtualFilePointer.getPresentableUrl()));
expandMacroToPathMap.addMacroExpand("FileParentPath", parentFile.getAbsolutePath());
return expandMacroToPathMap;
}
public ReplacePathToMacroMap createReplaceMacroToPathMap() {
final ReplacePathToMacroMap replacePathToMacroMap = new ReplacePathToMacroMap();
replacePathToMacroMap.put(myVirtualFilePointer.getFileName(), "$FileName$");
replacePathToMacroMap.addMacroReplacement(myVirtualFilePointer.getPresentableUrl(), "FilePath");
File parentFile = FileUtilRt.getParentFile(new File(myVirtualFilePointer.getPresentableUrl()));
replacePathToMacroMap.addMacroReplacement(parentFile.getAbsolutePath(), "FileParentPath");
return replacePathToMacroMap;
}
@Override
public boolean isEnabled() {
return myEnabled;
}
@Override
public void setEnabled(boolean enabled) {
myEnabled = enabled;
}
@NotNull
@Override
public String getProviderName() {
return myProviderName;
}
@NotNull
@Override
public String getName() {
return myName;
}
@Nullable
@Override
public BackgroundTaskByVfsChangeProvider getProvider() {
return myProvider;
}
@NotNull
@Override
public VirtualFilePointer getVirtualFilePointer() {
return myVirtualFilePointer;
}
@NotNull
@Override
public BackgroundTaskByVfsParameters getParameters() {
return myParameters;
}
@RequiredReadAction
@NotNull
@Override
public String[] getGeneratedFilePaths() {
if (myGeneratedFilePaths == null) {
myGeneratedFilePaths = generateFilePaths();
}
return myGeneratedFilePaths;
}
@RequiredReadAction
@NotNull
@Override
public VirtualFile[] getGeneratedFiles() {
String[] generatedFilePaths = getGeneratedFilePaths();
if (generatedFilePaths.length == 0) {
return VirtualFile.EMPTY_ARRAY;
}
List<VirtualFile> list = new ArrayList<VirtualFile>();
for (String generatedFilePath : generatedFilePaths) {
VirtualFile fileByPath = LocalFileSystem.getInstance().findFileByPath(generatedFilePath);
if (fileByPath != null) {
list.add(fileByPath);
}
}
return VfsUtilCore.toVirtualFileArray(list);
}
@NotNull
@RequiredReadAction
private String[] generateFilePaths() {
if (myProvider == null) {
return ArrayUtil.EMPTY_STRING_ARRAY;
}
VirtualFile file = myVirtualFilePointer.getFile();
if (file == null) {
return ArrayUtil.EMPTY_STRING_ARRAY;
}
String[] generatedFiles = myProvider.getGeneratedFiles(myProject, file);
if (generatedFiles.length == 0) {
return ArrayUtil.EMPTY_STRING_ARRAY;
}
ExpandMacroToPathMap expandOutMacroToPathMap = createExpandOutMacroToPathMap();
String[] allPaths = new String[generatedFiles.length];
for (int i = 0; i < generatedFiles.length; i++) {
String generatedFile = generatedFiles[i];
String expanded = expandOutMacroToPathMap.substitute(generatedFile, SystemInfo.isFileSystemCaseSensitive);
allPaths[i] = expanded;
}
return allPaths;
}
@NotNull
@Override
public Project getProject() {
return myProject;
}
@NotNull
@Override
public BackgroundTaskByVfsChangeTask clone() {
BackgroundTaskByVfsChangeTaskImpl task =
new BackgroundTaskByVfsChangeTaskImpl(myProject, myVirtualFilePointer, myParameters, myProviderName, myName, myProvider, myManager);
task.setEnabled(isEnabled());
return task;
}
public void parameterUpdated() {
myGeneratedFilePaths = null;
myManager.taskChanged(this);
}
}