net.oualid.maven.plugins.SurefireDashboardPlugin.java Source code

Java tutorial

Introduction

Here is the source code for net.oualid.maven.plugins.SurefireDashboardPlugin.java

Source

package net.oualid.maven.plugins;

/*
 * Copyright 2001-2005 The Apache Software Foundation.
 *
 * 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.
 */

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.maven.doxia.markup.HtmlMarkup;
import org.apache.maven.doxia.sink.Sink;
import org.apache.maven.doxia.sink.SinkEventAttributeSet;
import org.apache.maven.doxia.sink.SinkEventAttributes;
import org.apache.maven.doxia.siterenderer.Renderer;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;
import org.apache.maven.reporting.AbstractMavenReport;
import org.apache.maven.reporting.MavenReportException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;

@Mojo(name = "surefiredashboard", defaultPhase = LifecyclePhase.TEST, threadSafe = true, requiresDependencyResolution = ResolutionScope.TEST)
public class SurefireDashboardPlugin extends AbstractMavenReport {
    /**
     * Report output directory.
     *
     * @parameter expression="${project.build.directory}"
     * @required
     */
    @Parameter(property = "outputDirectory", defaultValue = "${project.build.directory}")
    private File outputDirectory;

    /**
     * Maximum test boxes per line.
     *
     * @parameter default-value="5"
     * @required
     */
    @Parameter(property = "maxTestsPerLine", defaultValue = "5", required = true)
    private int maxTestsPerLine;

    @Parameter(property = "webservicesToCallOnError")
    private List<String> webservicesToCallOnError;

    @Override
    protected Renderer getSiteRenderer() {
        return null;
    }

    @Override
    protected String getOutputDirectory() {
        return outputDirectory.getAbsolutePath();
    }

    @Override
    protected MavenProject getProject() {
        return null;
    }

    @Override
    protected void executeReport(Locale locale) throws MavenReportException {

        getLog().info("Max tests per line: " + maxTestsPerLine);

        File f = outputDirectory;

        File resourceFile = new File(f, "site");
        resourceFile = new File(resourceFile, "surefiredashboard");

        flushResource("/surefiredashboard.css", new File(resourceFile, "surefiredashboard.css"));
        flushResource("/surefiredashboard.js", new File(resourceFile, "surefiredashboard.js"));

        getLog().info("Looking for surefire reports in " + f + "...");

        File surefireReportDirectory = new File(f, "surefire-reports");

        Sink sink = getSink();

        sink.head();
        sink.title();
        sink.text("Surefire dashboard");
        sink.title_();

        SinkEventAttributeSet atts = new SinkEventAttributeSet();
        atts.addAttribute(SinkEventAttributes.TYPE, "text/javascript");
        atts.addAttribute(SinkEventAttributes.SRC, "surefiredashboard/surefiredashboard.js");
        sink.unknown("script", new Object[] { new Integer(HtmlMarkup.TAG_TYPE_START) }, atts);
        sink.unknown("script", new Object[] { new Integer(HtmlMarkup.TAG_TYPE_END) }, null);

        atts = new SinkEventAttributeSet();
        atts.addAttribute(SinkEventAttributes.HREF, "surefiredashboard/surefiredashboard.css");
        atts.addAttribute(SinkEventAttributes.REL, "stylesheet");
        atts.addAttribute(SinkEventAttributes.TYPE, "text/css");
        atts.addAttribute("media", "all");

        sink.unknown("link", new Object[] { new Integer(HtmlMarkup.TAG_TYPE_START) }, atts);
        sink.unknown("link", new Object[] { new Integer(HtmlMarkup.TAG_TYPE_END) }, null);

        sink.head_();

        sink.body();
        sink.section1();
        sink.sectionTitle1();

        sink.text("Surefire dashboard");

        sink.sectionTitle1_();
        sink.section1_();

        atts = new SinkEventAttributeSet();
        atts.addAttribute(SinkEventAttributes.CLASS, "generatedOn");
        sink.unknown("div", new Object[] { new Integer(HtmlMarkup.TAG_TYPE_START) }, atts);
        SimpleDateFormat df = new SimpleDateFormat("yyyyy-mm-dd hh:mm:ss");

        sink.text("Last published: " + df.format(new Date()));
        sink.unknown("div", new Object[] { new Integer(HtmlMarkup.TAG_TYPE_END) }, null);

        File[] files = surefireReportDirectory.listFiles(new FilenameFilter() {
            public boolean accept(File dir, String name) {
                return name.toLowerCase().endsWith(".xml");
            }
        });
        if (files == null) {
            getLog().warn("no surefire tests found !");
        } else {
            for (int i = 0; i < files.length; i++) {
                File file = files[i];
                getLog().info("Found surefire report: " + file.getName());

                DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
                DocumentBuilder documentBuilder = null;
                try {
                    documentBuilder = documentBuilderFactory.newDocumentBuilder();
                    Document document = documentBuilder.parse(files[i]);
                    NodeList nodes = document.getElementsByTagName("testcase");

                    atts = new SinkEventAttributeSet();
                    atts.addAttribute(SinkEventAttributes.CLASS, "testClassContainer");
                    sink.unknown("div", new Object[] { new Integer(HtmlMarkup.TAG_TYPE_START) }, atts);

                    atts = new SinkEventAttributeSet();
                    atts.addAttribute(SinkEventAttributes.CLASS, "testClassTitle");
                    sink.unknown("div", new Object[] { new Integer(HtmlMarkup.TAG_TYPE_START) }, atts);
                    Element suite = (Element) document.getElementsByTagName("testsuite").item(0);
                    sink.text(suite.getAttribute("name"));
                    sink.unknown("div", new Object[] { new Integer(HtmlMarkup.TAG_TYPE_END) }, null);

                    atts = new SinkEventAttributeSet();
                    atts.addAttribute(SinkEventAttributes.CLASS, "testClass");
                    sink.unknown("div", new Object[] { new Integer(HtmlMarkup.TAG_TYPE_START) }, atts);

                    for (int j = 0; j < nodes.getLength(); j++) {

                        if (j > 0 && j % maxTestsPerLine == 0) {
                            sink.unknown("div", new Object[] { new Integer(HtmlMarkup.TAG_TYPE_END) }, null);

                            atts = new SinkEventAttributeSet();
                            atts.addAttribute(SinkEventAttributes.CLASS, "testClass");
                            sink.unknown("div", new Object[] { new Integer(HtmlMarkup.TAG_TYPE_START) }, atts);
                        }

                        Element node = (Element) nodes.item(j);
                        String name = node.getAttribute("name");
                        String time = node.getAttribute("time");

                        atts = new SinkEventAttributeSet();
                        boolean error = node.getElementsByTagName("error").getLength() > 0
                                || node.getElementsByTagName("failure").getLength() > 0;
                        atts.addAttribute(SinkEventAttributes.CLASS, "testCase " + (error ? "error" : "success"));

                        sink.unknown("div", new Object[] { new Integer(HtmlMarkup.TAG_TYPE_START) }, atts);
                        atts = new SinkEventAttributeSet();
                        sink.unknown("span", new Object[] { new Integer(HtmlMarkup.TAG_TYPE_START) }, atts);
                        sink.text(name);
                        sink.unknown("span", new Object[] { new Integer(HtmlMarkup.TAG_TYPE_END) }, null);

                        atts = new SinkEventAttributeSet();
                        atts.addAttribute(SinkEventAttributes.CLASS, "duration");
                        sink.unknown("span", new Object[] { new Integer(HtmlMarkup.TAG_TYPE_START) }, atts);
                        sink.text(time);
                        sink.unknown("span", new Object[] { new Integer(HtmlMarkup.TAG_TYPE_END) }, null);
                        sink.unknown("div", new Object[] { new Integer(HtmlMarkup.TAG_TYPE_END) }, null);

                        if (error && webservicesToCallOnError != null && webservicesToCallOnError.size() > 0) {
                            for (String ws : webservicesToCallOnError) {
                                ws = StringUtils.replace(ws, "{{testname}}", name);
                                callWebservice(ws);
                            }
                        }
                    }

                    sink.unknown("div", new Object[] { new Integer(HtmlMarkup.TAG_TYPE_END) }, null);
                    sink.unknown("div", new Object[] { new Integer(HtmlMarkup.TAG_TYPE_END) }, null);
                } catch (ParserConfigurationException e) {
                    getLog().error("Cannot generate section for surefire report: " + file.getName());
                } catch (SAXException e) {
                    getLog().error("Cannot generate section for surefire report: " + file.getName());
                } catch (IOException e) {
                    getLog().error("Cannot generate section for surefire report: " + file.getName());
                }

            }
        }

        sink.body_();
        sink.flush();
        sink.close();

        sink.body();

        if (!f.exists()) {
            f.mkdirs();
        }
    }

    private void callWebservice(String url) {
        CloseableHttpClient httpclient = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet(url);
        CloseableHttpResponse response = null;
        try {
            response = httpclient.execute(httpGet);
            getLog().info(url + " > " + response.getStatusLine());
            HttpEntity entity = response.getEntity();
            EntityUtils.consume(entity);
        } catch (IOException e) {
            getLog().error("Error calling ws: " + url, e);
        } finally {
            try {
                if (response != null)
                    response.close();
            } catch (IOException e) {
                getLog().error("Error calling ws: " + url, e);
            }
        }
    }

    private void flushResource(String source, File dest) {
        dest.getParentFile().mkdirs();
        BufferedOutputStream os = null;
        BufferedInputStream is = null;
        try {
            is = new BufferedInputStream(SurefireDashboardPlugin.class.getResourceAsStream(source));
            os = new BufferedOutputStream(new FileOutputStream(dest));
            IOUtils.copy(is, os);
        } catch (IOException e) {
            getLog().error("Cannot flush resource on file system", e);
        } finally {
            if (os != null) {
                try {
                    os.flush();
                    os.close();
                } catch (IOException e) {
                    getLog().error("Cannot flush resource on file system", e);
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    getLog().error("Cannot flush resource on file system", e);
                }
            }
        }
    }

    public String getOutputName() {
        return "surefire-dashboard";
    }

    public String getName(Locale locale) {
        return "Surefire dashboard";
    }

    public String getDescription(Locale locale) {
        return "A surefire dashboard";
    }
}