/*
* Copyright 2000-2013 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.
*/
package com.intellij.coldFusion.mxunit;
import com.intellij.coldFusion.CfmlBundle;
import com.intellij.coldFusion.UI.runner.CfmlRunConfiguration;
import com.intellij.coldFusion.model.files.CfmlFile;
import com.intellij.execution.DefaultExecutionResult;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.ExecutionResult;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.*;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.runners.ProgramRunner;
import com.intellij.execution.testframework.sm.SMTestRunnerConnectionUtil;
import com.intellij.execution.testframework.ui.BaseTestsOutputConsoleView;
import com.intellij.execution.ui.ConsoleView;
import com.intellij.openapi.options.SettingsEditor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.util.xmlb.XmlSerializer;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import java.io.OutputStream;
public class CfmlUnitRunConfiguration extends LocatableConfigurationBase {
private CfmlUnitRunnerParameters myRunnerParameters;
protected CfmlUnitRunConfiguration(final Project project, final ConfigurationFactory factory, final String name) {
super(project, factory, name);
myRunnerParameters = createRunnerParametersInstance();
}
@NotNull
@Override
public SettingsEditor<? extends RunConfiguration> getConfigurationEditor() {
return new CfmlUnitRunConfigurationForm(getProject());
}
private static class MyProcessHandler extends ProcessHandler {
@Override
protected void destroyProcessImpl() {
notifyProcessTerminated(0);
}
@Override
protected void detachProcessImpl() {
notifyProcessDetached();
}
@Override
public boolean detachIsDefault() {
return true;
}
@Override
public OutputStream getProcessInput() {
return null;
}
}
@Override
public RunProfileState getState(@NotNull Executor executor, @NotNull final ExecutionEnvironment env) throws ExecutionException {
return new RunProfileState() {
@Override
public ExecutionResult execute(Executor executor, @NotNull ProgramRunner runner) throws ExecutionException {
final ProcessHandler processHandler = new MyProcessHandler();
final ConsoleView console = createConsole(getProject(), processHandler, env, executor);
console.addMessageFilter(new CfmlStackTraceFilterProvider(getProject()));
// processHandler.startNotify();
runTests(processHandler);
return new DefaultExecutionResult(console, processHandler);
}
};
}
private static boolean isVirtualFileUnderSourceRoot(VirtualFile virtualFile, Project project) {
ProjectFileIndex index = ProjectRootManager.getInstance(project).getFileIndex();
if (virtualFile == null || index.getContentRootForFile(virtualFile) == null) {
return false;
}
return true;
}
@Override
public void checkConfiguration() throws RuntimeConfigurationException {
final CfmlUnitRunnerParameters params = getRunnerParameters();
final String path = params.getPath();
switch (params.getScope()) {
case Method:
case Component: {
if (StringUtil.isEmpty(path)) {
throw new RuntimeConfigurationError(CfmlBundle.message("cfml.runconfig.file.name.empty", path));
}
final VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByPath(path);
if (file == null || !file.isValid() || file.isDirectory()) {
throw new RuntimeConfigurationError(CfmlBundle.message("cfml.runconfig.file.not.found", path));
}
if (!isVirtualFileUnderSourceRoot(file, getProject())) {
throw new RuntimeConfigurationError(CfmlBundle.message("cfml.runconfig.file.not.in.project", path));
}
final PsiFile psiFile = PsiManager.getInstance(getProject()).findFile(file);
if (!(psiFile instanceof CfmlFile)) {
throw new RuntimeConfigurationException("Incorrect file type");
}
/*
final CfmlFile cfmlFile = (CfmlFile)psiFile;
PsiTreeUtil.getChildrenOfType(cfmlFile, CfmlTagImpl);
if ()
*/
}
break;
case Directory: {
if (StringUtil.isEmpty(path)) {
throw new RuntimeConfigurationError(CfmlBundle.message("cfml.runconfig.directory.name.empty", path));
}
final VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByPath(path);
if (file == null || !file.isValid() || !file.isDirectory()) {
throw new RuntimeConfigurationError(CfmlBundle.message("cfml.runconfig.directory.not.found", path));
}
if (!isVirtualFileUnderSourceRoot(file, getProject())) {
throw new RuntimeConfigurationError(CfmlBundle.message("cfml.runconfig.directory.not.in.project", path));
}
}
break;
}
// check URL
CfmlRunConfiguration.checkURL(params.getWebPath());
}
private ConsoleView createConsole(Project project, ProcessHandler processHandler, ExecutionEnvironment env, Executor executor)
throws ExecutionException {
final CfmlUnitRunConfiguration runConfiguration = (CfmlUnitRunConfiguration)env.getRunProfile();
final CfmlUnitConsoleProperties consoleProps = new CfmlUnitConsoleProperties(runConfiguration, executor);
consoleProps.addStackTraceFilter(new CfmlStackTraceFilterProvider(getProject()));
BaseTestsOutputConsoleView testsOutputConsoleView = SMTestRunnerConnectionUtil
.createAndAttachConsole("Cfml", processHandler, consoleProps, env);
Disposer.register(project, testsOutputConsoleView);
return testsOutputConsoleView;
}
private void runTests(ProcessHandler processHandler) throws ExecutionException {
CfmlUnitRemoteTestsRunner.
executeScript(getRunnerParameters(), processHandler/*webPath, componentFile,
params.getScope() == CfmlUnitRunnerParameters.Scope.Method ? params.getMethod() : "",
processHandler*/, getProject());
}
protected CfmlUnitRunnerParameters createRunnerParametersInstance() {
return new CfmlUnitRunnerParameters();
}
public CfmlUnitRunnerParameters getRunnerParameters() {
return myRunnerParameters;
}
@SuppressWarnings({"CloneDoesntDeclareCloneNotSupportedException", "CloneDoesntCallSuperClone"})
@Override
public CfmlUnitRunConfiguration clone() {
try {
Element element = new Element("tmp");
writeExternal(element);
CfmlUnitRunConfiguration clone =
new CfmlUnitRunConfiguration(getProject(), getFactory(), getName());
clone.readExternal(element);
return clone;
}
catch (WriteExternalException e) {
throw new RuntimeException(e);
}
catch (InvalidDataException e) {
throw new RuntimeException(e);
}
}
@Override
public void readExternal(final Element element) throws InvalidDataException {
super.readExternal(element);
myRunnerParameters = createRunnerParametersInstance();
XmlSerializer.deserializeInto(myRunnerParameters, element);
}
@Override
public void writeExternal(final Element element) throws WriteExternalException {
super.writeExternal(element);
if (myRunnerParameters != null) {
XmlSerializer.serializeInto(myRunnerParameters, element);
}
}
}