com.intellij.execution.testframework.export.ExportTestResultsAction.java Source code

Java tutorial

Introduction

Here is the source code for com.intellij.execution.testframework.export.ExportTestResultsAction.java

Source

/*
 * Copyright 2000-2012 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.execution.testframework.export;

import com.intellij.diagnostic.LogMessageEx;
import com.intellij.execution.ExecutionBundle;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.execution.testframework.TestFrameworkRunningModel;
import com.intellij.ide.BrowserUtil;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diagnostic.Attachment;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.progress.PerformInBackgroundOption;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.util.ExceptionUtil;
import com.intellij.util.PathUtil;
import com.intellij.util.io.URLUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.xml.sax.SAXException;

import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.TransformerException;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.net.URL;

public class ExportTestResultsAction extends DumbAwareAction {
    private static final String ID = "ExportTestResults";

    private static final Logger LOG = Logger.getInstance(ExportTestResultsAction.class.getName());

    private TestFrameworkRunningModel myModel;
    private String myToolWindowId;
    private RunConfiguration myRunConfiguration;

    public static ExportTestResultsAction create(String toolWindowId, RunConfiguration runtimeConfiguration) {
        ExportTestResultsAction action = new ExportTestResultsAction();
        action.copyFrom(ActionManager.getInstance().getAction(ID));
        action.myToolWindowId = toolWindowId;
        action.myRunConfiguration = runtimeConfiguration;
        return action;
    }

    public void setModel(TestFrameworkRunningModel model) {
        myModel = model;
    }

    @Override
    public void update(AnActionEvent e) {
        e.getPresentation().setEnabled(isEnabled(e.getDataContext()));
    }

    private boolean isEnabled(DataContext dataContext) {
        if (myModel == null) {
            return false;
        }

        if (CommonDataKeys.PROJECT.getData(dataContext) == null) {
            return false;
        }

        return !myModel.getRoot().isInProgress();
    }

    @Override
    public void actionPerformed(AnActionEvent e) {
        final Project project = CommonDataKeys.PROJECT.getData(e.getDataContext());
        LOG.assertTrue(project != null);
        final ExportTestResultsConfiguration config = ExportTestResultsConfiguration.getInstance(project);

        final String name = ExecutionBundle.message("export.test.results.filename",
                PathUtil.suggestFileName(myRunConfiguration.getName()));
        String filename = name + "." + config.getExportFormat().getDefaultExtension();
        boolean showDialog = true;
        while (showDialog) {
            final ExportTestResultsDialog d = new ExportTestResultsDialog(project, config, filename);
            d.show();
            if (!d.isOK()) {
                return;
            }
            filename = d.getFileName();
            showDialog = getOutputFile(config, project, filename).exists() && Messages.showOkCancelDialog(project,
                    ExecutionBundle.message("export.test.results.file.exists.message", filename),
                    ExecutionBundle.message("export.test.results.file.exists.title"),
                    Messages.getQuestionIcon()) != DialogWrapper.OK_EXIT_CODE;
        }

        final String filename_ = filename;
        ProgressManager.getInstance().run(new Task.Backgroundable(project,
                ExecutionBundle.message("export.test.results.task.name"), false, new PerformInBackgroundOption() {
                    @Override
                    public boolean shouldStartInBackground() {
                        return true;
                    }

                    @Override
                    public void processSentToBackground() {
                    }
                }) {
            @Override
            public void run(@NotNull ProgressIndicator indicator) {
                indicator.setIndeterminate(true);

                final File outputFile = getOutputFile(config, project, filename_);
                final String outputText;
                try {
                    outputText = getOutputText(config);
                    if (outputText == null) {
                        return;
                    }
                } catch (IOException ex) {
                    LOG.warn(ex);
                    showBalloon(project, MessageType.ERROR,
                            ExecutionBundle.message("export.test.results.failed", ex.getMessage()), null);
                    return;
                } catch (TransformerException ex) {
                    LOG.warn(ex);
                    showBalloon(project, MessageType.ERROR,
                            ExecutionBundle.message("export.test.results.failed", ex.getMessage()), null);
                    return;
                } catch (SAXException ex) {
                    LOG.warn(ex);
                    showBalloon(project, MessageType.ERROR,
                            ExecutionBundle.message("export.test.results.failed", ex.getMessage()), null);
                    return;
                } catch (RuntimeException ex) {
                    ExportTestResultsConfiguration c = new ExportTestResultsConfiguration();
                    c.setExportFormat(ExportTestResultsConfiguration.ExportFormat.Xml);
                    c.setOpenResults(false);
                    try {
                        String xml = getOutputText(c);
                        LOG.error(LogMessageEx.createEvent("Failed to export test results",
                                ExceptionUtil.getThrowableText(ex), null, null, new Attachment("dump.xml", xml)));
                    } catch (Throwable ignored) {
                        LOG.error("Failed to export test results", ex);
                    }
                    return;
                }

                final Ref<VirtualFile> result = new Ref<VirtualFile>();
                final Ref<String> error = new Ref<String>();
                ApplicationManager.getApplication().invokeAndWait(new Runnable() {
                    @Override
                    public void run() {
                        result.set(
                                ApplicationManager.getApplication().runWriteAction(new Computable<VirtualFile>() {
                                    @Override
                                    public VirtualFile compute() {
                                        outputFile.getParentFile().mkdirs();
                                        final VirtualFile parent = LocalFileSystem.getInstance()
                                                .refreshAndFindFileByIoFile(outputFile.getParentFile());
                                        if (parent == null || !parent.isValid()) {
                                            error.set(ExecutionBundle.message("failed.to.create.output.file",
                                                    outputFile.getPath()));
                                            return null;
                                        }

                                        try {
                                            VirtualFile result = parent.createChildData(this, outputFile.getName());
                                            VfsUtil.saveText(result, outputText);
                                            return result;
                                        } catch (IOException e) {
                                            LOG.warn(e);
                                            error.set(e.getMessage());
                                            return null;
                                        }
                                    }
                                }));
                    }
                }, ModalityState.defaultModalityState());

                if (!result.isNull()) {
                    if (config.isOpenResults()) {
                        openEditorOrBrowser(result.get(), project,
                                config.getExportFormat() == ExportTestResultsConfiguration.ExportFormat.Xml);
                    } else {
                        HyperlinkListener listener = new HyperlinkListener() {
                            @Override
                            public void hyperlinkUpdate(HyperlinkEvent e) {
                                if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
                                    openEditorOrBrowser(result.get(), project, config
                                            .getExportFormat() == ExportTestResultsConfiguration.ExportFormat.Xml);
                                }
                            }
                        };
                        showBalloon(project, MessageType.INFO,
                                ExecutionBundle.message("export.test.results.succeeded", outputFile.getName()),
                                listener);
                    }
                } else {
                    showBalloon(project, MessageType.ERROR,
                            ExecutionBundle.message("export.test.results.failed", error.get()), null);
                }
            }
        });
    }

    @NotNull
    private static File getOutputFile(final @NotNull ExportTestResultsConfiguration config,
            final @NotNull Project project, final @NotNull String filename) {
        final File outputFolder;
        final String outputFolderPath = config.getOutputFolder();
        if (!StringUtil.isEmptyOrSpaces(outputFolderPath)) {
            if (FileUtil.isAbsolute(outputFolderPath)) {
                outputFolder = new File(outputFolderPath);
            } else {
                outputFolder = new File(new File(project.getBasePath()), config.getOutputFolder());
            }
        } else {
            outputFolder = new File(project.getBasePath());
        }

        return new File(outputFolder, filename);
    }

    private static void openEditorOrBrowser(final VirtualFile result, final Project project, final boolean editor) {
        ApplicationManager.getApplication().invokeLater(new Runnable() {
            @Override
            public void run() {
                if (editor) {
                    FileEditorManager.getInstance(project).openFile(result, true);
                } else {
                    BrowserUtil.browse(result);
                }
            }
        });
    }

    @Nullable
    private String getOutputText(ExportTestResultsConfiguration config)
            throws IOException, TransformerException, SAXException {
        ExportTestResultsConfiguration.ExportFormat exportFormat = config.getExportFormat();

        SAXTransformerFactory transformerFactory = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
        TransformerHandler handler;
        if (exportFormat == ExportTestResultsConfiguration.ExportFormat.Xml) {
            handler = transformerFactory.newTransformerHandler();
            handler.getTransformer().setOutputProperty(OutputKeys.INDENT, "yes");
            handler.getTransformer().setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
        } else {
            Source xslSource;
            if (config.getExportFormat() == ExportTestResultsConfiguration.ExportFormat.BundledTemplate) {
                URL bundledXsltUrl = getClass().getResource("intellij-export.xsl");
                xslSource = new StreamSource(URLUtil.openStream(bundledXsltUrl));
            } else {
                File xslFile = new File(config.getUserTemplatePath());
                if (!xslFile.isFile()) {
                    showBalloon(myRunConfiguration.getProject(), MessageType.ERROR, ExecutionBundle
                            .message("export.test.results.custom.template.not.found", xslFile.getPath()), null);
                    return null;
                }
                xslSource = new StreamSource(xslFile);
            }
            handler = transformerFactory.newTransformerHandler(xslSource);
            handler.getTransformer().setParameter("TITLE", ExecutionBundle.message("export.test.results.filename",
                    myRunConfiguration.getName(), myRunConfiguration.getType().getDisplayName()));
        }

        StringWriter w = new StringWriter();
        handler.setResult(new StreamResult(w));
        TestResultsXmlFormatter.execute(myModel.getRoot(), myRunConfiguration, handler);
        return w.toString();
    }

    private void showBalloon(final Project project, final MessageType type, final String text,
            @Nullable final HyperlinkListener listener) {
        ApplicationManager.getApplication().invokeLater(new Runnable() {
            public void run() {
                if (project.isDisposed())
                    return;
                if (ToolWindowManager.getInstance(project).getToolWindow(myToolWindowId) != null) {
                    ToolWindowManager.getInstance(project).notifyByBalloon(myToolWindowId, type, text, null,
                            listener);
                }
            }
        });
    }

}