hudson.plugins.testcomplete.TestCompleteInputMetric.java Source code

Java tutorial

Introduction

Here is the source code for hudson.plugins.testcomplete.TestCompleteInputMetric.java

Source

/**
 * The MIT License
 * Copyright (c) 2015 Fernando Migulez Palomo and all contributors
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package hudson.plugins.testcomplete;

import hudson.plugins.testcomplete.mht.MHTEntry;
import hudson.plugins.testcomplete.mht.MHTException;
import hudson.plugins.testcomplete.mht.MHTInputStream;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;

import javax.xml.transform.stream.StreamSource;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.filefilter.FileFilterUtils;
import org.jenkinsci.lib.dtkit.model.InputMetricXSL;
import org.jenkinsci.lib.dtkit.model.InputType;
import org.jenkinsci.lib.dtkit.model.OutputMetric;
import org.jenkinsci.lib.dtkit.util.converter.ConversionException;
import org.jenkinsci.lib.dtkit.util.converter.ConversionService;
import org.jenkinsci.plugins.xunit.types.model.JUnitModel;

import com.google.common.io.Files;

/**
 * 
 * @author Fernando Migulez Palomo
 * 
 *
 */
public class TestCompleteInputMetric extends InputMetricXSL {

    private static final Logger logger = LogManager.getLogManager()
            .getLogger(TestCompleteInputMetric.class.getName());

    private final static String CONTENT_TYPE_XML = "text/xml";
    /**
     * Base URL links inside MHT and XML files refer to
     */
    private final static String INTERNAL_PARAM_BASE_URL = "baseUrl";
    /**
     * Path holding XML files
     */
    private final static String INTERNAL_PARAM_BASE_PATH = "basePath";

    /**
     * Parameter that defines the regular expression to apply to transformation
     * so only those tests matching it will be included
     */
    public final static String PARAM_TEST_PATTERN = "testPattern";

    /**
     * 
     */
    private static final long serialVersionUID = 6315183679905588379L;

    /**
     * Pattern provided by the user to apply a filtering to the tests results
     * (we may only want to filter out some tests from the results such as
     * start-up or tear-down type tests).
     */
    private String testFilterPattern = "";

    @Override
    public InputType getToolType() {
        return InputType.TEST;
    }

    @Override
    public String getToolName() {
        return Messages.testcomplete_toolName();
    }

    @Override
    public String getToolVersion() {
        return "10.x";
    }

    @Override
    public String getXslName() {
        return "testcomplete-10-to-junit-1.0.xsl";
    }

    protected void setTestFilterPattern(String testFilterPattern) {
        this.testFilterPattern = testFilterPattern != null ? testFilterPattern.trim() : "";
    }

    /**
     * Gets the Class (namespace) of the xsl file resource
     *
     * @return the resource class (for loading)
     */
    @Override
    public Class<?> getXslResourceClass() {
        return this.getClass();
    }

    @Override
    public String[] getInputXsdNameList() {
        return null;
    }

    @Override
    public OutputMetric getOutputFormatType() {
        return JUnitModel.LATEST;
    }

    /**
     * This method extracts all XML files inside a MHT file produced by
     * TestComplete/TestExecute into a temporary directory and returns a
     * reference to such directory.
     * 
     * @param inputFile
     *            MHT file to process
     * @param params
     *            map where parameter with key "baseUrl" and value returned by
     *            {@link MHTInputStream#getBaseUrl()} is added
     * @return temporary file that contains all the extracted XML files from
     *         input MHT file
     * @throws MHTException
     *             if and MHT error occurs
     * @throws IOException
     *             if an I/O error ocurrs
     */
    private File extractXMLFilesFromMHTFile(File inputFile, Map<String, Object> params) throws IOException {
        File tempDir = Files.createTempDir();
        MHTInputStream mis = null;

        try {
            mis = new MHTInputStream(new FileInputStream(inputFile));

            if (params != null) {
                params.put(INTERNAL_PARAM_BASE_URL, mis.getBaseUrl());
                // It seems that backslashes should be escaped in XSL references
                // so we just convert to UNIX format
                // that works also on Windows for Java.
                params.put(INTERNAL_PARAM_BASE_PATH, FilenameUtils.normalize(tempDir.getAbsolutePath(), true));
            }

            MHTEntry entry = null;
            byte buffer[] = new byte[1024];
            int readBytes = 0;

            while ((entry = mis.getNextEntry()) != null) {
                if (CONTENT_TYPE_XML.equals(entry.getContentType())) {
                    File out = new File(tempDir, entry.getName());
                    out.createNewFile();
                    FileOutputStream fos = new FileOutputStream(out);
                    try {
                        while ((readBytes = mis.read(buffer)) > 0) {
                            fos.write(buffer, 0, readBytes);
                        }
                    } finally {
                        fos.close();
                    }
                }
            }

            return tempDir;

        } catch (IOException e) {
            // Cleanup temporary directory here upon failure
            FileUtils.deleteDirectory(tempDir);
            throw e;
        } finally {
            if (mis != null) {
                mis.close();
            }
        }
    }

    @Override
    public void convert(File inputFile, File outFile, Map<String, Object> params) throws ConversionException {
        File inputTempDir = null;
        Map<String, Object> conversionParams = new HashMap<String, Object>();
        if (params != null) {
            conversionParams.putAll(params);
        }

        try {
            inputTempDir = extractXMLFilesFromMHTFile(inputFile, conversionParams);

            Collection<File> xmlFiles = FileUtils.listFiles(inputTempDir,
                    FileFilterUtils.nameFileFilter("root.xml"), null);
            if (xmlFiles.isEmpty()) {
                throw new ConversionException(
                        "Invalid TestComplete MHT file '" + inputFile.getName() + "'. No 'root.xml' found.");
            }

            File rootXml = xmlFiles.iterator().next();

            /*
             * TODO We are unable to pass testFilterPattern as specified by user
             * because xUnit does not pass the TestType instance
             * (TestCompleteTestType). Base plugin should be extended to pass
             * customized parameters.
             */
            if (testFilterPattern.length() > 0) {
                if (testFilterPattern.startsWith("^") || testFilterPattern.endsWith("$")) {
                    /*
                     * We do not allow these special symbols because they will
                     * make our pattern to fail, since provided pattern is only
                     * part of another pattern that matches test names.
                     */
                    throw new ConversionException("Invalid test filter pattern provided '" + testFilterPattern
                            + "'. Start (^) and end ($) line pattern symbols are not allowed.");
                }

                if (logger.isLoggable(Level.INFO)) {
                    logger.info("Applying test filter pattern '" + testFilterPattern + "' to TestComplete test: "
                            + inputFile.getName());
                }
                conversionParams.put(PARAM_TEST_PATTERN, testFilterPattern);
            }

            ConversionService conversionService = new ConversionService();
            if (getXslFile() == null) {
                conversionService.convert(
                        new StreamSource(this.getXslResourceClass().getResourceAsStream(getXslName())), rootXml,
                        outFile, conversionParams);
            } else {
                conversionService.convert(getXslFile(), rootXml, outFile, conversionParams);
            }
        } catch (IOException e) {
            throw new ConversionException("Errors parsing input MHT file '" + inputFile.getName() + "'", e);
        } finally {

            if (inputTempDir != null) {
                try {
                    FileUtils.deleteDirectory(inputTempDir);
                } catch (IOException e) {

                }
            }
        }
    }
}