/*******************************************************************************
 * Copyright (c) 2000, 2016 IBM Corporation and others. All rights reserved.
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors: IBM Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.releng.generators;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.Vector;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
import org.eclipse.releng.generators.TestResultsGenerator.ResultsTable.Cell;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 * @version 1.0
 * @author Dean Roberts (circa 2000!) and David Williams (circa 2016)
 */
public class TestResultsGenerator extends Task {

    public class ResultsTable implements Iterable<String> {

        private Map<String, Row> rows    = new TreeMap();
        private List<String>     columns = new ArrayList();

        public ResultsTable(ArrayList<String> columns) {
            super();
            this.columns = columns;
        }

        public class Cell {

            private Integer errorCount  = null;
            private File    resultsFile = null;

            public Cell(int errorCount, File resultsFile) {
                super();
                this.errorCount = errorCount;
                this.resultsFile = resultsFile;
            }

            public Integer getErrorCount() {
                return errorCount;
            }

            public File getResultsFile() {
                return resultsFile;
            }
        }

        private class Row {

            Map<String, Cell> row = new TreeMap();

            public Row(List<String> columns) {
                super();
                for (String column : columns) {
                    row.put(column, null);
                }
            }

            public Cell getCell(String column) {
                Cell cell = row.get(column);
                return cell;
            }

            public void putCell(String columnName, Integer cellValue, File file) {
                row.put(columnName, new Cell(cellValue, file));
            }
        }

        private Row getRow(String rowname) {
            Row row = rows.get(rowname);
            if (row == null) {
                row = new Row(columns);
                rows.put(rowname, row);
            }
            return row;
        }

        public Cell getCell(String rowName, String columnName) {
            Cell result = getRow(rowName).getCell(columnName);
            return result;
        }

        public int getCellErrorCount(String rowName, String columnName) {
            int result = -1;
            Cell cell = getRow(rowName).getCell(columnName);
            result = cell.getErrorCount();
            return result;
        }

        public File getCellResultsFile(String rowName, String columnName) {
            File result = null;
            Cell cell = getRow(rowName).getCell(columnName);
            result = cell.getResultsFile();
            return result;
        }

        public void putCell(String rowName, String columnName, Integer cellValue, File file) {
            getRow(rowName).putCell(columnName, cellValue, file);
        }

        List<String> getColumns() {
            return columns;
        }

        public void setColumns(List<String> columns) {
            if (this.columns != null) {
                throw new RuntimeException("The columns for the table were already defined");
            }
            this.columns = columns;
        }

        public Iterator<String> iterator() {
            return rows.keySet().iterator();
        }
    }

    private static final String HTML_EXTENSION                 = ".html";
    private static final String XML_EXTENSION                  = ".xml";
    private static final String WARNING_SEVERITY               = "WARNING";
    private static final String ERROR_SEVERITY                 = "ERROR";
    private static final String ForbiddenReferenceID           = "ForbiddenReference";
    private static final String DiscouragedReferenceID         = "DiscouragedReference";

    private static final int    DEFAULT_READING_SIZE           = 8192;

    private static final String elementName                    = "testsuite";

    private ArrayList<String>   expectedConfigs                = null;
    private static final String EOL                            = System.getProperty("line.separator");
    private static boolean      DEBUG                          = false;
    private static String       FOUND_TEST_CONFIGS_FILENAME    = "testConfigsFound.php";

    private static String       EXPECTED_TEST_CONFIGS_FILENAME = "testConfigs.php";
    private static String       expected_config_type           = "expected";
    private Vector              dropTokens;

    private String              testResultsWithProblems        = EOL;
    private String              testResultsXmlUrls             = EOL;

    private DocumentBuilder     parser                         = null;
    private ErrorTracker        anErrorTracker;

    private String              dropTemplateString             = "";

    // Parameters
    // build runs JUnit automated tests
    private boolean             isBuildTested;

    // buildType, I, N
    private String              buildType;

    // Comma separated list of drop tokens
    private String              dropTokenList;

    // Location of the xml files
    private String              xmlDirectoryName;

    // Location of the html files
    private String              htmlDirectoryName;

    // Location of the resulting index.php file.
    private String              dropDirectoryName;

    // Location and name of the template drop index.php file.
    private String              dropTemplateFileName;

    // Name of the HTML fragment file that any testResults.php file will
    // "include".
    // setting to common default.
    private String              testResultsHtmlFileName        = "testResultsRows.html";

    // Name of the generated drop index php file;
    private String              dropHtmlFileName;

    // Arbitrary path used in the index.php page to href the
    // generated .html files.
    private String              hrefTestResultsTargetPath;
    // Arbitrary path used in the index.php page to reference the compileLogs
    private String              hrefCompileLogsTargetPath;
    // Location of compile logs base directory
    private String              compileLogsDirectoryName;
    // Location and name of test manifest file
    private String              testManifestFileName;
    // private static String testsConstant = ".tests";
    // private static int testsConstantLength = testsConstant.length();
    // temporary way to force "missing" list not to be printed (until complete
    // solution found)
    private boolean             doMissingList                  = true;

    private Set<String>         missingManifestFiles           = Collections.checkedSortedSet(new TreeSet(), String.class);

    class ExpectedConfigFiler implements FilenameFilter {

        String configEnding;

        public ExpectedConfigFiler(String expectedConfigEnding) {
            configEnding = expectedConfigEnding;
        }

        public boolean accept(File dir, String name) {
            return (name.endsWith(configEnding));
        }

    }

    private String extractXmlRelativeFileName(final String rootCanonicalPath, final File xmlFile) {
        if (rootCanonicalPath != null) {
            String xmlFileCanonicalPath = null;
            try {
                xmlFileCanonicalPath = xmlFile.getCanonicalPath();
            }
            catch (final IOException e) {
                logException(e);
            }
            if (xmlFileCanonicalPath != null) {
                // + 1 to remove the '\'
                return xmlFileCanonicalPath.substring(rootCanonicalPath.length() + 1).replace('\\', '/');
            }
        }
        return "";
    }

    private void logException(final Throwable e) {
        log(e.getMessage());
        StackTraceElement[] stackTrace = e.getStackTrace();
        for (StackTraceElement stackTraceElement : stackTrace) {
            log(stackTraceElement.toString());
        }
    }

    private static byte[] getFileByteContent(final String fileName) throws IOException {
        InputStream stream = null;
        try {
            final File file = new File(fileName);
            stream = new BufferedInputStream(new FileInputStream(file));
            return getInputStreamAsByteArray(stream, (int) file.length());
        }
        finally {
            if (stream != null) {
                try {
                    stream.close();
                }
                catch (final IOException e) {
                    // ignore
                }
            }
        }
    }

    /**
     * Returns the given input stream's contents as a byte array. If a length is
     * specified (ie. if length != -1), only length bytes are returned.
     * Otherwise all bytes in the stream are returned. Note this doesn't close
     * the stream.
     * 
     * @throws IOException
     *             if a problem occurred reading the stream.
     */
    private static byte[] getInputStreamAsByteArray(final InputStream stream, final int length) throws IOException {
        byte[] contents;
        if (length == -1) {
            contents = new byte[0];
            int contentsLength = 0;
            int amountRead = -1;
            do {
                final int amountRequested = Math.max(stream.available(), DEFAULT_READING_SIZE);

                // resize contents if needed
                if ((contentsLength + amountRequested) > contents.length) {
                    System.arraycopy(contents, 0, contents = new byte[contentsLength + amountRequested], 0, contentsLength);
                }

                // read as many bytes as possible
                amountRead = stream.read(contents, contentsLength, amountRequested);

                if (amountRead > 0) {
                    // remember length of contents
                    contentsLength += amountRead;
                }
            }
            while (amountRead != -1);

            // resize contents if necessary
            if (contentsLength < contents.length) {
                System.arraycopy(contents, 0, contents = new byte[contentsLength], 0, contentsLength);
            }
        } else {
            contents = new byte[length];
            int len = 0;
            int readSize = 0;
            while ((readSize != -1) && (len != length)) {
                // See PR 1FMS89U
                // We record first the read size. In this case len is the actual
                // read size.
                len += readSize;
                readSize = stream.read(contents, len, length - len);
            }
        }

        return contents;
    }

    public static void main(final String[] args) {
        final TestResultsGenerator test = new TestResultsGenerator();
        if (Boolean.FALSE) {
            test.setTestsConfigExpected(
                    "ep46N-unit-cen64_linux.gtk.x86_64_8.0, ep46N-unit-lin64_linux.gtk.x86_64_8.0 ,ep46N-unit-mac64_macosx.cocoa.x86_64_8.0 ,ep46N-unit-win32_win32.win32.x86_8.0");
            DEBUG = true;
            try {
                test.getTestsConfig();
            }
            catch (IOException e) {
                e.printStackTrace();
            }

        } else {
            test.setTestsConfigExpected(
                    "ep46N-unit-lin64_linux.gtk.x86_64_8.0 ,ep46N-unit-mac64_macosx.cocoa.x86_64_8.0 ,ep46N-unit-win32_win32.win32.x86_8.0, ep46N-unit-cen64_linux.gtk.x86_64_8.0");
            // "%equinox%,%framework%,%extrabundles%,%other%,%incubator%,%provisioning%,%launchers%,%osgistarterkits%");
            test.setDropTokenList(
                    "%sdk%,%tests%,%example%,%rcpruntime%,%rcpsdk%,%deltapack%,%runtime%,%jdt%,%jdtsdk%,%jdtc%,%pde%,%pdesdk%,%cvs%,%cvssdk%,%swt%,%relengtools%");
            test.getDropTokensFromList(test.dropTokenList);
            test.setIsBuildTested(true);
            test.setXmlDirectoryName(
                    "/data/shared/eclipse/buildsmirror/4N/siteDir/eclipse/downloads/drops4/N20160409-0230/testresults/xml");
            test.setHtmlDirectoryName(
                    "/data/shared/eclipse/buildsmirror/4N/siteDir/eclipse/downloads/drops4/N20160409-0230/testresults");
            test.setDropDirectoryName("/data/shared/eclipse/buildsmirror/4N/siteDir/eclipse/downloads/drops4/N20160409-0230");

            test.setDropTemplateFileName(
                    "/home/davidw/gitNeon/eclipse.platform.releng.aggregator/eclipse.platform.releng.tychoeclipsebuilder/eclipse/publishingFiles/templateFiles/index.template.php");
            test.setTestResultsHtmlFileName("testResultsRows.html");
            test.setDropHtmlFileName("index.php");

            test.setHrefTestResultsTargetPath("testresults");
            test.setCompileLogsDirectoryName(
                    "/data/shared/eclipse/buildsmirror/4N/siteDir/eclipse/downloads/drops4/N20160409-0230/compilelogs/plugins");
            test.setHrefCompileLogsTargetPath("compilelogs/plugins/");
            test.setTestManifestFileName(
                    "/home/davidw/gitNeon/eclipse.platform.releng.aggregator/eclipse.platform.releng.tychoeclipsebuilder/eclipse/publishingFiles/testManifest.xml");
            test.execute();
        }
    }

    // Configuration of test machines.
    // Add or change new configurations here
    // and update titles in testResults.template.php.
    // These are the suffixes used for JUnit's XML output files.
    // On each invocation, all files in results directory are
    // scanned, to see if they end with suffixes, and if so,
    // are processed for summary row. The column order is determined by
    // the order listed here.
    // This suffix is determined, at test time, when the files junit files are
    // generated, by the setting of a variable named "platform" in test.xml
    // and associated property files.

    // no defaults set since adds to confusion or errors
    // private String[] testsConfigDefaults = { "ep4" + getTestedBuildType() +
    // "-unit-lin64_linux.gtk.x86_64_8.0.xml",
    // "ep4" + getTestedBuildType() + "-unit-mac64_macosx.cocoa.x86_64_8.0.xml",
    // "ep4" + getTestedBuildType() + "-unit-win32_win32.win32.x86_8.0.xml",
    // "ep4" + getTestedBuildType() + "-unit-cen64_linux.gtk.x86_64_8.0.xml" };
    private String  testsConfigExpected;
    private boolean testRan;
    private String  compilerSummaryFilename = "compilerSummary.html";

    private int countCompileErrors(final String aString) {
        return extractNumber(aString, "error");
    }

    private int countCompileWarnings(final String aString) {
        return extractNumber(aString, "warning");
    }

    private int countDiscouragedWarnings(final String aString) {
        return extractNumber(aString, "Discouraged access:");
    }

    /*
     * returns number of errors plus number of failures. returns a negative
     * number if the file is missing or something is wrong with the file (such
     * as is incomplete).
     */
    private int countErrors(final String fileName) {
        int errorCount = -99;
        // File should exists, since we are "driving" this based on file list
        // ... but, just in case.
        if (!new File(fileName).exists()) {
            errorCount = -1;
        } else {

            if (new File(fileName).length() == 0) {
                errorCount = -2;
            } else {

                try {
                    final DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
                    parser = docBuilderFactory.newDocumentBuilder();

                    final Document document = parser.parse(fileName);
                    final NodeList elements = document.getElementsByTagName(elementName);

                    final int elementCount = elements.getLength();
                    if (elementCount == 0) {
                        errorCount = -3;
                    } else {
                        for (int i = 0; i < elementCount; i++) {
                            final Element element = (Element) elements.item(i);
                            final NamedNodeMap attributes = element.getAttributes();
                            Node aNode = attributes.getNamedItem("errors");
                            errorCount = Integer.parseInt(aNode.getNodeValue());
                            aNode = attributes.getNamedItem("failures");
                            errorCount = errorCount + Integer.parseInt(aNode.getNodeValue());
                        }
                    }

                }
                catch (final IOException e) {
                    log("IOException: " + fileName);
                    logException(e);
                    errorCount = -4;
                }
                catch (final SAXException e) {
                    log("SAXException: " + fileName);
                    logException(e);
                    errorCount = -5;
                }
                catch (final ParserConfigurationException e) {
                    logException(e);
                    errorCount = -6;
                }
            }
        }
        return errorCount;
    }

    private int countForbiddenWarnings(final String aString) {
        return extractNumber(aString, "Access restriction:");
    }

    @Override
    public void execute() {

        anErrorTracker = new ErrorTracker();
        anErrorTracker.loadFile(getTestManifestFileName());
        getDropTokensFromList(getDropTokenList());
        dropTemplateString = readFile(getDropTemplateFileName());

        writeDropIndexFile();

        try {
            parseCompileLogs();
        }
        catch (IOException e) {
            throw new BuildException("Error while parsing Compiler Results File ", e);
        }

        if (isBuildTested()) {

            try {
                parseJUnitTestsXml();

            }
            catch (IOException e) {
                throw new BuildException("Error while parsing JUnit Tests Results Files", e);
            }

        } else {
            log("isBuildTested value was not true, so did no processing for test files");
        }
        log("Completed processing test and build results");
    }

    private int extractNumber(final String aString, final String endToken) {
        final int endIndex = aString.lastIndexOf(endToken);
        if (endIndex == -1) {
            return 0;
        }

        int startIndex = endIndex;
        while ((startIndex >= 0) && (aString.charAt(startIndex) != '(') && (aString.charAt(startIndex) != ',')) {
            startIndex--;
        }

        final String count = aString.substring(startIndex + 1, endIndex).trim();
        try {
            return Integer.parseInt(count);
        }
        catch (final NumberFormatException e) {
            return 0;
        }

    }

    private void formatAccessesErrorRow(final String fileName, final int forbiddenAccessesWarningsCount,
            final int discouragedAccessesWarningsCount, final StringBuffer buffer) {

        if ((forbiddenAccessesWarningsCount == 0) && (discouragedAccessesWarningsCount == 0)) {
            return;
        }

        String relativeName = computeRelativeName(fileName);
        String shortName = computeShortName(relativeName);

        buffer.append("<tr>").append(EOL).append("<td>").append(EOL).append("<a href=").append("\"").append(relativeName)
                .append("\">").append(shortName).append("</a>").append("</td>\n").append("<td style=\"text-align:center\" >")
                .append("<a href=").append("\"").append(relativeName).append("#FORBIDDEN_WARNINGS").append("\">")
                .append(forbiddenAccessesWarningsCount).append("</a>").append("</td>").append(EOL)
                .append("<td style=\"text-align:center\" >").append("<a href=").append("\"").append(relativeName)
                .append("#DISCOURAGED_WARNINGS").append("\">").append(discouragedAccessesWarningsCount).append("</a>")
                .append("</td>").append(EOL).append("</tr>").append(EOL);
    }

    private String computeRelativeName(final String fileName) {
        String relativeName;
        final int i = fileName.indexOf(getHrefCompileLogsTargetPath());
        relativeName = fileName.substring(i);
        return relativeName;
    }

    private String computeShortName(final String relativeName) {
        String shortName;

        final int start = getHrefCompileLogsTargetPath().length();
        final int lastslash = relativeName.lastIndexOf("/");
        // if there is no "last slash", that's a pretty weird case, but we'll
        // just
        // take the whole rest of string in that case.
        if (lastslash == -1) {
            shortName = relativeName.substring(start);
        } else {
            shortName = relativeName.substring(start, lastslash);
        }
        return shortName;
    }

    private void formatCompileErrorRow(final String fileName, final int errorCount, final int warningCount,
            final StringBuffer buffer) {

        if ((errorCount == 0) && (warningCount == 0)) {
            return;
        }

        String relativeName = computeRelativeName(fileName);
        String shortName = computeShortName(relativeName);

        buffer.append("<tr>\n<td>\n").append("<a href=").append("\"").append(relativeName).append("\">").append(shortName)
                .append("</a>").append("</td>\n").append("<td style=\"text-align:center\" >").append("<a href=").append("\"")
                .append(relativeName).append("#ERRORS").append("\">").append(errorCount).append("</a>").append("</td>\n")
                .append("<td style=\"text-align:center\" >").append("<a href=").append("\"").append(relativeName)
                .append("#OTHER_WARNINGS").append("\">").append(warningCount).append("</a>").append("</td>\n").append("</tr>\n");
    }

    public String getBuildType() {
        return buildType;
    }

    /**
     * Gets the compileLogsDirectoryName.
     * 
     * @return Returns a String
     */
    public String getCompileLogsDirectoryName() {
        return compileLogsDirectoryName;
    }

    public String getDropDirectoryName() {
        return dropDirectoryName;
    }

    /**
     * Gets the dropHtmlFileName.
     * 
     * @return Returns a String
     */
    public String getDropHtmlFileName() {
        return dropHtmlFileName;
    }

    /**
     * Gets the dropTemplateFileName.
     * 
     * @return Returns a String
     */
    public String getDropTemplateFileName() {
        return dropTemplateFileName;
    }

    public String getDropTokenList() {
        return dropTokenList;
    }

    /**
     * @return
     */
    public Vector getDropTokens() {
        return dropTokens;
    }

    private void getDropTokensFromList(final String list) {
        final StringTokenizer tokenizer = new StringTokenizer(list, ",");
        dropTokens = new Vector();

        while (tokenizer.hasMoreTokens()) {
            dropTokens.add(tokenizer.nextToken());
        }
    }

    /**
     * Gets the hrefCompileLogsTargetPath.
     * 
     * @return Returns a String
     */
    public String getHrefCompileLogsTargetPath() {
        return hrefCompileLogsTargetPath;
    }

    /**
     * Gets the hrefTestResultsTargetPath.
     * 
     * @return Returns a String
     */
    public String getHrefTestResultsTargetPath() {
        return hrefTestResultsTargetPath;
    }

    public String getHtmlDirectoryName() {
        return htmlDirectoryName;
    }

    /**
     * Gets the testManifestFileName.
     * 
     * @return Returns a String
     */
    public String getTestManifestFileName() {
        return testManifestFileName;
    }

    public String getTestResultsHtmlFileName() {
        return testResultsHtmlFileName;
    }

    /**
     * @return
     */
    public String getTestResultsWithProblems() {
        return testResultsWithProblems;
    }

    /**
     * @return
     */
    public String getTestResultsXmlUrls() {
        return testResultsXmlUrls;
    }

    public String getXmlDirectoryName() {
        return xmlDirectoryName;
    }

    public boolean isBuildTested() {
        return isBuildTested;
    }

    private void parseCompileLog(final String log, final StringBuffer compilerLog, final StringBuffer accessesLog) {
        int errorCount = 0;
        int warningCount = 0;
        int forbiddenWarningCount = 0;
        int discouragedWarningCount = 0;

        final File file = new File(log);
        Document aDocument = null;
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader(file));
            final InputSource inputSource = new InputSource(reader);
            final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            final DocumentBuilder builder = factory.newDocumentBuilder();
            aDocument = builder.parse(inputSource);
        }
        catch (final SAXException e) {
            logException(e);
        }
        catch (final IOException e) {
            logException(e);
        }
        catch (final ParserConfigurationException e) {
            logException(e);
        }
        finally {
            if (reader != null) {
                try {
                    reader.close();
                }
                catch (final IOException e) {
                    // ignore
                }
            }
        }

        if (aDocument == null) {
            return;
        }
        // Get summary of problems
        final NodeList nodeList = aDocument.getElementsByTagName("problem");
        if ((nodeList == null) || (nodeList.getLength() == 0)) {
            return;
        }

        final int length = nodeList.getLength();
        for (int i = 0; i < length; i++) {
            final Node problemNode = nodeList.item(i);
            final NamedNodeMap aNamedNodeMap = problemNode.getAttributes();
            final Node severityNode = aNamedNodeMap.getNamedItem("severity");
            final Node idNode = aNamedNodeMap.getNamedItem("id");
            if (severityNode != null) {
                final String severityNodeValue = severityNode.getNodeValue();
                if (WARNING_SEVERITY.equals(severityNodeValue)) {
                    // this is a warning
                    // need to check the id
                    final String nodeValue = idNode.getNodeValue();
                    if (ForbiddenReferenceID.equals(nodeValue)) {
                        forbiddenWarningCount++;
                    } else if (DiscouragedReferenceID.equals(nodeValue)) {
                        discouragedWarningCount++;
                    } else {
                        warningCount++;
                    }
                } else if (ERROR_SEVERITY.equals(severityNodeValue)) {
                    // this is an error
                    errorCount++;
                }
            }
        }
        if (errorCount != 0) {
            // use wildcard in place of version number on directory names
            // log(log + "/n");
            String logName = log.substring(getCompileLogsDirectoryName().length() + 1);
            final StringBuffer buffer = new StringBuffer(logName);
            buffer.replace(logName.indexOf("_") + 1, logName.indexOf(File.separator, logName.indexOf("_") + 1), "*");
            logName = new String(buffer);

            anErrorTracker.registerError(logName);
        }
        // make sure '.xml' extension is "last thing" in string. (bug 490320)
        final String logName = log.replaceAll(XML_EXTENSION + "$", HTML_EXTENSION);
        formatCompileErrorRow(logName, errorCount, warningCount, compilerLog);
        formatAccessesErrorRow(logName, forbiddenWarningCount, discouragedWarningCount, accessesLog);
    }

    private void parseCompileLogs() throws IOException {
        File sourceDirectory = new File(getCompileLogsDirectoryName());
        File mainDir = new File(getDropDirectoryName());
        File compilerSummaryFile = new File(mainDir, compilerSummaryFilename);
        // we do not recompute compiler summary each time, since it is
        // fairly time consuming -- and no reason it would not be "complete",
        // if it exists.
        if (compilerSummaryFile.exists()) {
            log("Compile logs summary page, " + compilerSummaryFilename + ", was found to exist already, so not recomputed.");
        } else {
            log("Parsing compile logs");
            String compileLogResults = "";
            final StringBuffer compilerString = new StringBuffer();
            final StringBuffer accessesString = new StringBuffer();
            processCompileLogsDirectory(getCompileLogsDirectoryName(), compilerString, accessesString);
            if (compilerString.length() == 0) {
                compilerString
                        .append("<tr><td>None</td><td style=\"text-align:center\">&nbsp;</td><td style=\"text-align:center\">&nbsp;</td></tr>"
                                + EOL);
            }
            if (accessesString.length() == 0) {
                accessesString
                        .append("<tr><td>None</td><td style=\"text-align:center\">&nbsp;</td><td style=\"text-align:center\">&nbsp;</td></tr>"
                                + EOL);
            }

            compileLogResults = "        <div class=\"homeitem3col\">" + EOL
                    + "<h3 id=\"PluginsErrors\">Plugins containing compile errors or warnings</h3>" + EOL
                    + "<p>The table below shows the plugins in which errors or warnings were encountered. Click on the jar file link to view its"
                    + EOL + "detailed report.</p>" + EOL + "<br /><br />" + EOL
                    + "<table style=\"background-color: #EEEEEE;margin-top: 20px; margin-bottom: 20px; margin-right: 5%; margin-left: 5%; width:90%; border: 1px solid black; \" >"
                    + EOL + "  <tr>" + EOL + "    <th>Compile Logs (Jar Files)</th>" + EOL
                    + "    <th style=\"width:15em\">Errors</th>" + EOL + "    <th style=\"width:15em\">Warnings</th>" + EOL
                    + "  </tr>" + EOL;

            compileLogResults = compileLogResults + compilerString.toString();

            compileLogResults = compileLogResults + "          </table>" + EOL
                    + "<h3 id=\"AcessErrors\">Plugins containing access errors or warnings</h3>" + EOL
                    + "<table style=\"background-color: #EEEEEE;margin-top: 20px; margin-bottom: 20px; margin-right: 5%; margin-left: 5%; width:90%; border: 1px solid black; \" >"
                    + EOL + " <tr>" + EOL + "    <th>Compile Logs (Jar Files)</th>" + EOL
                    + "   <th style=\"width:15em; \">Forbidden Access Warnings</th>" + EOL
                    + "   <th style=\"width:15em ;\" >Discouraged Access Warnings</th>" + EOL + " </tr>" + EOL;

            compileLogResults = compileLogResults + accessesString.toString();
            compileLogResults = compileLogResults + "</table>" + EOL + "  <br /> " + EOL + "</div>" + EOL;
            // write the include file. The name of this file must match what is
            // in testResults.template.php
            writePhpIncludeCompilerResultsFile(sourceDirectory, compileLogResults);
            log("End: Generating compile logs summary page");
        }
    }

    private void parseJUnitTestsXml() throws IOException {
        log("Begin: Parsing XML JUnit results files");
        ArrayList<String> foundConfigs = new ArrayList();
        final File xmlResultsDirectory = new File(getXmlDirectoryName());
        ResultsTable resultsTable = new ResultsTable(getTestsConfig());
        if (xmlResultsDirectory.exists()) {
            // reinitialize each time.
            // We currently "re do" all of tests, but can improve in the future
            // where the "found configs" are remembered, but then have to keep
            // track of original order (not "found" order which has to with when
            // tests completed).
            foundConfigs.clear();

            ArrayList<File> allFileNames = new ArrayList();

            for (String expectedConfig : getTestsConfig()) {

                FilenameFilter configfilter = new ExpectedConfigFiler("_" + expectedConfig + XML_EXTENSION);
                // we end with "full" list of files, sorted by configfilter, and
                // then alphabetical.
                File[] xmlFileNamesForConfig = xmlResultsDirectory.listFiles(configfilter);

                if (xmlFileNamesForConfig.length > 0) {
                    // log("DEBUG: For " + expectedConfig + " found " +
                    // xmlFileNamesForConfig.length + " XML results files");
                    foundConfigs.add(expectedConfig);
                    // sort by name, for each 'config' found.
                    Arrays.sort(xmlFileNamesForConfig);
                    for (File file : xmlFileNamesForConfig) {
                        allFileNames.add(file);
                    }
                }
            }
            File[] xmlFileNames = new File[allFileNames.size()];
            allFileNames.toArray(xmlFileNames);
            // files MUST be alphabetical, for now?
            Arrays.sort(xmlFileNames);
            String sourceDirectoryCanonicalPath = getDropDirectoryName();
            for (int i = 0; i < xmlFileNames.length; i++) {
                File junitResultsFile = xmlFileNames[i];
                checkIfMissingFromTestManifestFile(junitResultsFile, foundConfigs);
                String fullName = junitResultsFile.getPath();
                int errorCount = countErrors(fullName);
                resultsTable.putCell(computeCoreName(junitResultsFile), computeConfig(junitResultsFile), errorCount,
                        junitResultsFile);
                if (errorCount != 0) {
                    trackDataForMail(sourceDirectoryCanonicalPath, junitResultsFile, fullName);
                }
            }
        } else {
            // error? Or, just too early?
            log("WARNING: sourceDirectory did not exist at \n\t" + xmlResultsDirectory);
            log("     either incorrect call to 'generate index' or called too early (tests not done yet)?");
        }
        log("End: Parsing XML JUnit results files");
        // above is all "compute data". Now it is time to "display" it.
        if (foundConfigs.size() > 0) {
            log("Begin: Generating test results index page");
            setTestsRan(true);
            writeHTMLResultsTable(foundConfigs, resultsTable);
            log("End: Generating test results index page");
        } else {
            setTestsRan(false);
            log("Test results not found in " + xmlResultsDirectory.getAbsolutePath());
        }

    }

    private void writeHTMLResultsTable(ArrayList<String> foundConfigs, ResultsTable resultsTable) throws IOException {
        // These first files reflect what we expected, and what we found.
        String found_config_type = "found";
        writePhpConfigFile(found_config_type, foundConfigs, FOUND_TEST_CONFIGS_FILENAME);
        // write the table to main output directory in testResultsRows.html, which
        // in turn is included by the testResults.php file.

        // first we right a bit of "static" part. That comes before the table.

        String htmlString = "<p>The unit tests are run on the <a href=\"https://hudson.eclipse.org/shared/view/Eclipse%20and%20Equinox/\">shared Hudson instance</a>.</p>"
                + EOL;

        htmlString = htmlString + "<p>The table shows the unit test results for this build on the platforms" + EOL;
        htmlString = htmlString + "tested. You may access the test results page specific to each" + EOL;
        htmlString = htmlString + "component on a specific platform by clicking the cell link." + EOL;
        htmlString = htmlString + "Normally, the number of errors is indicated in the cell.</p>" + EOL;
        htmlString = htmlString + "<p>A \"-1\" or \"DNF\" means the test \"Did Not Finish\" for unknown reasons" + EOL;
        htmlString = htmlString + "and hence no results page is available. In that case," + EOL;
        htmlString = htmlString + "more information can sometimes be found in" + EOL;
        htmlString = htmlString + "the <a href=\"logs.php#console\">console logs</a>.</p>" + EOL;
        htmlString = htmlString + "<?php" + EOL;
        htmlString = htmlString + "if (file_exists(\"testNotes.html\")) {" + EOL;
        htmlString = htmlString + "  $my_file = file_get_contents(\"testNotes.html\");" + EOL;
        htmlString = htmlString + "  echo $my_file;" + EOL;
        htmlString = htmlString + "}" + EOL;
        htmlString = htmlString + "?>" + EOL;


        htmlString = htmlString + startTableOfUnitResults();
        for (String row : resultsTable) {
            htmlString = htmlString + formatJUnitRow(row, resultsTable, foundConfigs);
        }
        // Once we are done with the Unit tests rows, we must add end table
        // tag, since the following methods may or may not add a table of
        // their own.
        htmlString = htmlString + EOL + "</table>" + EOL;
        // check for missing test logs
        htmlString = htmlString + verifyAllTestsRan(xmlDirectoryName, foundConfigs);
        htmlString = htmlString + listMissingManifestFiles();
        writeTestResultsFile(htmlString);
    }

    private String startTableOfUnitResults() throws IOException {
        String result = "";
        long width = 90;
        long half = width / 2;
        int ncolumns = getTestsConfig().size();
        /*
         * unsure if 'percent' can be "real" number, or if must be integer? if
         * needs to be integer, use ($a - ($a % $b)) / $b;
         */
        long colWidth = half / ncolumns;
        // table
        result = result
                + "<table style=\"background-color: #EEEEEE; margin-top: 20px; margin-bottom: 20px; margin-right: 5%; margin-left: 5%; width:"
                + width + "%; border: 1px solid black \" >" + EOL;
        // table header
        result = result + "<tr style=\"background-color: #9999CC\" >" + EOL;
        result = result + "<th style=\"width: " + width + "%; text-align:center\" "
                + " rowspan='2' > org.eclipse <br /> Test Bundles </th>\n" + EOL;
        result = result + "<th style=\"text-align:center; \" colspan='" + ncolumns
                + "'> Test Configurations (Hudson Job/os.ws.arch/VM) </th>" + EOL;
        result = result + "</tr>\n";
        // end table header
        result = result + "<tr style=\"background-color: #9999CC\">" + EOL;

        for (String column : getTestsConfig()) {
            result = result + "<th style=\"width: " + colWidth + "%; \" >" + computeDisplayConfig(column) + "</th>\n";
        }
        result = result + "</tr>\n";
        return result;
    }

    /*
     * This function "breaks" the full config string at meaningful underscores,
     * for improved display in tables and similar. Remember, some config values
     * can have more than two underscores, such as
     * ep46N-unit-lin64_linux.gtk.x86_64_8.0, which should be split as
     * ep46N-unit-lin64 lin64_linux.gtk.x86_64 8.0
     */
    private String computeDisplayConfig(String config) {
        int lastUnderscore = config.lastIndexOf("_");
        int firstUnderscore = config.indexOf('_');
        // echo "<br/>DEBUG: config: config firstUnderscore: firstUnderscore
        // lastUnderscore: lastUnderscore lastMinusFirst: platformLength"
        String jobname = config.substring(0, firstUnderscore);
        String platformconfig = config.substring(firstUnderscore + 1, lastUnderscore);
        String vmused = config.substring(lastUnderscore + 1);
        // echo "DEBUG: jobname: ".jobname."<br/>";
        // echo "DEBUG: platformconfig: ".platformconfig."<br/>";
        // echo "DEBUG: vmused: ".vmused."<br/>";
        return jobname + "<br/>" + platformconfig + "<br/>" + vmused;

    }

    private void setTestsRan(boolean b) {
        testRan = b;
    }

    /*
     * As far as I know, this "work" was done to track data send out in an
     * email.
     */
    private void trackDataForMail(String sourceDirectoryCanonicalPath, File junitResultsFile, final String fullName) {
        final String testName = junitResultsFile.getName().substring(0,
                junitResultsFile.getName().length() - XML_EXTENSION.length());
        testResultsWithProblems = testResultsWithProblems.concat(EOL + testName);
        testResultsXmlUrls = testResultsXmlUrls
                .concat(EOL + extractXmlRelativeFileName(sourceDirectoryCanonicalPath, junitResultsFile));
        anErrorTracker.registerError(fullName.substring(getXmlDirectoryName().length() + 1));
    }

    /*
     * This is the "reverse" of checking for "missing test results". It is
     * simple sanity check to see if all "known" test results are listed in in
     * the testManifest.xml file. We only do this check if we also are checking
     * for missing logs which depends on an accurate testManifest.xml file.
     */
    private void checkIfMissingFromTestManifestFile(File junitResultsFile, ArrayList<String> foundConfigs) {
        if (doMissingList) {
            if (!verifyLogInManifest(junitResultsFile.getName(), foundConfigs)) {
                String corename = computeCoreName(junitResultsFile);
                missingManifestFiles.add(corename);
            }
        }
    }

    private String computeCoreName(File junitResultsFile) {
        String fname = junitResultsFile.getName();
        // corename is all that needs to be listed in testManifest.xml
        String corename = null;
        int firstUnderscorepos = fname.indexOf('_');
        if (firstUnderscorepos == -1) {
            // should not occur, but if it does, we will take whole name
            corename = fname;
        } else {
            corename = fname.substring(0, firstUnderscorepos);
        }
        return corename;
    }

    private String computeConfig(File junitResultsFile) {
        String fname = junitResultsFile.getName();
        String configName = null;
        int firstUnderscorepos = fname.indexOf('_');
        if (firstUnderscorepos == -1) {
            // should not occur, but if it does, we will set to null
            // and let calling program decide what to do.
            configName = null;
        } else {
            int lastPos = fname.lastIndexOf(XML_EXTENSION);
            if (lastPos == -1) {
                configName = null;
            } else {
                configName = fname.substring(firstUnderscorepos + 1, lastPos);
            }
        }
        return configName;
    }

    private void writePhpConfigFile(String config_type, ArrayList<String> configs, String phpfilename) throws IOException {
        File mainDir = new File(getDropDirectoryName());
        File testConfigsFile = new File(mainDir, phpfilename);
        Writer testconfigsPHP = new FileWriter(testConfigsFile);
        testconfigsPHP.write("<?php" + EOL);
        testconfigsPHP.write("//This file created by 'generateIndex' ant task, while parsing test results" + EOL);
        testconfigsPHP.write("// It is based on " + config_type + " testConfigs" + EOL);
        String phpArrayVariableName = "$" + config_type + "TestConfigs";
        testconfigsPHP.write(phpArrayVariableName + " = array();" + EOL);
        for (String fConfig : configs) {
            testconfigsPHP.write(phpArrayVariableName + "[]=\"" + fConfig + "\";" + EOL);
        }
        testconfigsPHP.close();
    }

    private void writePhpIncludeCompilerResultsFile(final File sourceDirectory, String compilerSummary) throws IOException {
        File mainDir = new File(getDropDirectoryName());
        File compilerSummaryFile = new File(mainDir, compilerSummaryFilename);
        Writer compilerSummaryPHP = new FileWriter(compilerSummaryFile);
        compilerSummaryPHP.write("<!--" + EOL);
        compilerSummaryPHP.write("  This file created by 'generateIndex' ant task, while parsing build and tests results" + EOL);
        compilerSummaryPHP.write("-->" + EOL);
        compilerSummaryPHP.write(compilerSummary);
        compilerSummaryPHP.close();
    }

    private void processCompileLogsDirectory(final String directoryName, final StringBuffer compilerLog,
            final StringBuffer accessesLog) {
        final File sourceDirectory = new File(directoryName);
        if (sourceDirectory.isFile()) {
            if (sourceDirectory.getName().endsWith(".log")) {
                readCompileLog(sourceDirectory.getAbsolutePath(), compilerLog, accessesLog);
            }
            if (sourceDirectory.getName().endsWith(XML_EXTENSION)) {
                parseCompileLog(sourceDirectory.getAbsolutePath(), compilerLog, accessesLog);
            }
        }
        if (sourceDirectory.isDirectory()) {
            final File[] logFiles = sourceDirectory.listFiles();
            Arrays.sort(logFiles);
            for (int j = 0; j < logFiles.length; j++) {
                processCompileLogsDirectory(logFiles[j].getAbsolutePath(), compilerLog, accessesLog);
            }
        }
    }

    private String processDropRow(final PlatformStatus aPlatform) {
        if ("equinox".equalsIgnoreCase(aPlatform.getFormat())) {
            return processEquinoxDropRow(aPlatform);
        } else {
            return processEclipseDropRow(aPlatform);
        }

    }

    private String processEclipseDropRow(PlatformStatus aPlatform) {
        String result = "<tr>\n<td>" + aPlatform.getName() + "</td>\n";
        // generate file link, size and checksums in the php template
        result = result + "<?php genLinks(\"" + aPlatform.getFileName() + "\"); ?>\n";
        result = result + "</tr>\n";
        return result;
    }

    private String processDropRows(final PlatformStatus[] platforms) {
        String result = "";
        for (int i = 0; i < platforms.length; i++) {
            result = result + processDropRow(platforms[i]);
        }
        return result;
    }

    /*
     * Generate and return the HTML mark-up for a single row for an Equinox JAR
     * on the downloads page.
     */
    private String processEquinoxDropRow(final PlatformStatus aPlatform) {
        String result = "<tr>";
        // result = result + "<td style=\"text-align:center\" >" +
        // getStatusColumn(aPlatform, "/equinox/images/", true) + "</td>\n";
        result = result + "<td>";
        final String filename = aPlatform.getFileName();
        // if there are images, put them in the same table column as the name of
        // the file
        final List images = aPlatform.getImages();
        if ((images != null) && !images.isEmpty()) {
            for (final Iterator iter = images.iterator(); iter.hasNext();) {
                result = result + "<img src=\"" + iter.next() + "\"/>&nbsp;";
            }
        }
        result = result + "<a href=\"download.php?dropFile=" + filename + "\">" + filename + "</a></td>\n";
        result = result + "{$generateDropSize(\"" + filename + "\")}\n";
        result = result + "{$generateChecksumLinks(\"" + filename + "\", $buildlabel)}\n";
        result = result + "</tr>\n";
        return result;
    }

    private void readCompileLog(final String log, final StringBuffer compilerLog, final StringBuffer accessesLog) {
        final String fileContents = readFile(log);

        final int errorCount = countCompileErrors(fileContents);
        final int warningCount = countCompileWarnings(fileContents);
        final int forbiddenWarningCount = countForbiddenWarnings(fileContents);
        final int discouragedWarningCount = countDiscouragedWarnings(fileContents);
        if (errorCount != 0) {
            // use wildcard in place of version number on directory names
            String logName = log.substring(getCompileLogsDirectoryName().length() + 1);
            final StringBuffer stringBuffer = new StringBuffer(logName);
            stringBuffer.replace(logName.indexOf("_") + 1, logName.indexOf(File.separator, logName.indexOf("_") + 1), "*");
            logName = new String(stringBuffer);

            anErrorTracker.registerError(logName);
        }
        formatCompileErrorRow(log, errorCount, warningCount, compilerLog);
        formatAccessesErrorRow(log, forbiddenWarningCount, discouragedWarningCount, accessesLog);
    }

    private String readFile(final String fileName) {
        byte[] aByteArray = null;
        try {
            aByteArray = getFileByteContent(fileName);
        }
        catch (final IOException e) {
            logException(e);
        }
        if (aByteArray == null) {
            return "";
        }
        return new String(aByteArray);
    }

    private String replace(final String source, final String original, final String replacement) {

        final int replaceIndex = source.indexOf(original);
        if (replaceIndex > -1) {
            String resultString = source.substring(0, replaceIndex);
            resultString = resultString + replacement;
            resultString = resultString + source.substring(replaceIndex + original.length());
            return resultString;
        } else {
            log("Could not find token: " + original);
            return source;
        }

    }

    public void setBuildType(final String buildType) {
        this.buildType = buildType;
    }

    /**
     * Sets the compileLogsDirectoryName.
     * 
     * @param compileLogsDirectoryName
     *            The compileLogsDirectoryName to set
     */
    public void setCompileLogsDirectoryName(final String compileLogsDirectoryName) {
        this.compileLogsDirectoryName = compileLogsDirectoryName;
    }

    public void setDropDirectoryName(final String aString) {
        dropDirectoryName = aString;
    }

    /**
     * Sets the dropHtmlFileName.
     * 
     * @param dropHtmlFileName
     *            The dropHtmlFileName to set
     */
    public void setDropHtmlFileName(final String dropHtmlFileName) {
        this.dropHtmlFileName = dropHtmlFileName;
    }

    /**
     * Sets the dropTemplateFileName.
     * 
     * @param dropTemplateFileName
     *            The dropTemplateFileName to set
     */
    public void setDropTemplateFileName(final String dropTemplateFileName) {
        this.dropTemplateFileName = dropTemplateFileName;
    }

    public void setDropTokenList(final String dropTokenList) {
        this.dropTokenList = dropTokenList;
    }

    /**
     * @param vector
     */
    public void setDropTokens(final Vector vector) {
        dropTokens = vector;
    }

    /**
     * Sets the hrefCompileLogsTargetPath.
     * 
     * @param hrefCompileLogsTargetPath
     *            The hrefCompileLogsTargetPath to set
     */
    public void setHrefCompileLogsTargetPath(final String hrefCompileLogsTargetPath) {
        this.hrefCompileLogsTargetPath = hrefCompileLogsTargetPath;
    }

    /**
     * Sets the hrefTestResultsTargetPath.
     * 
     * @param hrefTestResultsTargetPath
     *            The hrefTestResultsTargetPath to set
     */
    public void setHrefTestResultsTargetPath(final String htmlTargetPath) {
        hrefTestResultsTargetPath = htmlTargetPath;
    }

    public void setHtmlDirectoryName(final String aString) {
        htmlDirectoryName = aString;
    }

    public void setIsBuildTested(final boolean isBuildTested) {
        this.isBuildTested = isBuildTested;
    }

    /**
     * Sets the testManifestFileName.
     * 
     * @param testManifestFileName
     *            The testManifestFileName to set
     */
    public void setTestManifestFileName(final String testManifestFileName) {
        this.testManifestFileName = testManifestFileName;
    }

    public void setTestResultsHtmlFileName(final String aString) {
        testResultsHtmlFileName = aString;
    }

    /**
     * @param string
     */
    public void setTestResultsWithProblems(final String string) {
        testResultsWithProblems = string;
    }

    public void setXmlDirectoryName(final String aString) {
        xmlDirectoryName = aString;
    }

    private String verifyAllTestsRan(final String directory, ArrayList<String> foundConfigs) {
        String replaceString = "";
        ArrayList<String> missingFiles = new ArrayList();
        if (getDoMissingList()) {
            for (String testLogName : anErrorTracker.getTestLogs(foundConfigs)) {

                if (new File(directory + File.separator + testLogName).exists()) {
                    // log("DEBUG: found log existed: " + testLogName);
                    continue;
                }
                // log("DEBUG: found log DID NOT exist: " + testLogName);
                anErrorTracker.registerError(testLogName);
                // replaceString = replaceString + tmp;
                // testResultsWithProblems appears to be for email, or similar?
                testResultsWithProblems = testResultsWithProblems
                        .concat(EOL + testLogName.substring(0, testLogName.length() - XML_EXTENSION.length()) + " (file missing)");
                missingFiles.add(testLogName);
            }
        } else {
            // Note: we intentionally do not deal with missing file for perf.
            // tests yet.
            // (though, probably could, once fixed with "expected configs").
            replaceString = replaceString + "<tbody>\n" + "<tr><td colspan=\"0\"><p><span class=\"footnote\">NOTE: </span>\n"
                    + "Remember that for performance unit test tables, there are never any \"missing files\" listed, if there are any. \n"
                    + "This is expected to be a temporary solution, until an exact fix can be implemented. For more details, see \n"
                    + "<a href=\"https://bugs.eclipse.org/bugs/show_bug.cgi?id=451890\">bug 451890</a>.</p>\n" + "</td></tr>\n"
                    + "</tbody>\n";
        }
        // TODO: we need lots more of separating "data" from "formating"
        if (getDoMissingList() && missingFiles.size() > 0) {
            String ordinalWord = "File";
            if (missingFiles.size() > 1) {
                ordinalWord = "Files";
            }

            replaceString = replaceString + "</table><br />" + EOL
                    + "<table style=\"background-color: #EEEEEE; margin-top: 20px; margin-bottom: 20px; margin-right: 5px; margin-left: 5px; width:90%; border: 1px solid black;\" rules=\"rows\" >"
                    + "<tr style=\"background-color: #9999CC\"> <th  style=\"text-align:center\">Missing " + ordinalWord
                    + "</th></tr>";
            for (String testLogName : missingFiles) {
                replaceString = replaceString + EOL + "<tr><td>" + testLogName + "</td></tr>";
            }
            replaceString = replaceString + EOL + "</table>";
        }
        return replaceString;
    }

    private void writeDropIndexFile() {
        log("Begin: Generating drop index page");
        final String[] types = anErrorTracker.getTypes();
        for (int i = 0; i < types.length; i++) {
            final PlatformStatus[] platforms = anErrorTracker.getPlatforms(types[i]);
            final String replaceString = processDropRows(platforms);
            dropTemplateString = replace(dropTemplateString, dropTokens.get(i).toString(), replaceString);
        }
        final String outputFileName = dropDirectoryName + File.separator + dropHtmlFileName;
        writeFile(outputFileName, dropTemplateString);
        log("End: Generating drop index page");
    }

    private void writeFile(final String outputFileName, final String contents) {
        OutputStream outputStream = null;
        try {
            outputStream = new BufferedOutputStream(new FileOutputStream(outputFileName));
            outputStream.write(contents.getBytes());
        }
        catch (final FileNotFoundException e) {
            log("File not found exception writing: " + outputFileName);
        }
        catch (final IOException e) {
            log("IOException writing: " + outputFileName);
        }
        finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                }
                catch (final IOException e) {
                    // ignore
                }
            }
        }
    }

    /*
     * This method writes the computed HTML to the file specified by caller in
     * testResultsHtmlFileName. There must be an appropriate file on Download
     * site that "includes" the file.
     * 
     * @param contents
     */
    private void writeTestResultsFile(String contents) {
        final String outputFileName = dropDirectoryName + File.separator + testResultsHtmlFileName;
        writeFile(outputFileName, contents);

    }

    public String getTestsConfigExpected() {

        return testsConfigExpected;
    }

    public void setTestsConfigExpected(String testsConfigExpected) {
        this.testsConfigExpected = testsConfigExpected;
        // log("DEBUG: testsConfigExpected: " + testsConfigExpected);
    }

    private ArrayList<String> getTestsConfig() throws IOException {
        if (expectedConfigs == null) {
            expectedConfigs = new ArrayList<String>();
            String expectedConfigParam = getTestsConfigExpected();
            if (expectedConfigParam != null) {
                StringTokenizer tokenizer = new StringTokenizer(expectedConfigParam, " ,\t");
                while (tokenizer.hasMoreTokens()) {
                    expectedConfigs.add(tokenizer.nextToken());
                }
            } else {
                throw new BuildException("test configurations were not found. One or more must be set.");
            }
            if (DEBUG) {
                // log("DEBUG: testsConfig array ");
                for (String expected : expectedConfigs) {
                    log("\tDEBUG: expectedTestConfig: " + expected);
                }
            }
            // write expected test config file here. This file is later used by
            // the PHP file.
            writePhpConfigFile(expected_config_type, expectedConfigs, EXPECTED_TEST_CONFIGS_FILENAME);
        }
        return expectedConfigs;
    }

    public boolean getDoMissingList() {
        return doMissingList;
    }

    public void setDoMissingList(boolean doMissingList) {
        this.doMissingList = doMissingList;
    }

    /*
     * This is the reverse of checking that all expected logs were found. If
     * logs were found that are NOT in the test manifest, we write the list
     * below missing files, so that they can be added to testManifest.xml. This
     * allows them to be detected as missing, in future. We only do this check
     * if "doMissingList" is true.
     */
    private boolean verifyLogInManifest(String filename, ArrayList<String> foundConfigs) {
        boolean result = false;
        if (getDoMissingList()) {
            for (String testLogName : anErrorTracker.getTestLogs(foundConfigs)) {
                if (filename.equals(testLogName)) {
                    result = true;
                    break;
                }
            }
        }
        return result;
    }

    private String listMissingManifestFiles() throws IOException {
        String results = "";
        if (getDoMissingList()) {
            String xmlFragment = "<?xml version=\"1.0\" encoding=\"UTF-8\"?> " + EOL + "<topLevel>" + EOL;

            if (getDoMissingList() && missingManifestFiles.size() > 0) {
                String ordinalWord = "File";
                if (missingManifestFiles.size() > 1) {
                    ordinalWord = "Files";
                }

                results = results + EOL
                        + "<table style=\"background-color: #EEEEEE; margin-top: 20px; margin-bottom: 20px; margin-right: 5px; margin-left: 5px; width:90%; border: 1px solid black; \" rules=\"rows\" align=\"center\">"
                        + "<tr style=\"background-color: #9999CC\"> <th style=\"text-align:center; width:80%\" >Releng: <a href=\"addToTestManifest.xml\">Missing testManifest.xml "
                        + ordinalWord + "</a></th></tr>";
                for (String testLogName : missingManifestFiles) {
                    results = results + EOL + "<tr><td>" + testLogName + "</td></tr>";
                    xmlFragment = xmlFragment + "<logFile " + EOL + "  name=\"" + testLogName + "\"" + EOL + "  type=\"test\" />"
                            + EOL;
                }
                results = results + EOL + "</table>";
                xmlFragment = xmlFragment + "</topLevel>";
                FileWriter xmlOutput = new FileWriter(getDropDirectoryName() + "/addToTestManifest.xml");
                xmlOutput.write(xmlFragment);
                xmlOutput.close();
            }
        }
        return results;
    }

    // Specific to the RelEng test results page
    private String formatJUnitRow(String corename, ResultsTable resultsTable, ArrayList<String> foundConfigs) throws IOException {

        String results = "";
        int orgEclipseLength = "org.eclipse.".length();
        // indexOf('_') assumes never part of file name?
        final String displayName = corename.substring(orgEclipseLength);

        results = results + EOL + "<tr><td>" + displayName + "</td>";

        for (String config : getTestsConfig()) {
            Cell cell = resultsTable.getCell(corename, config);
            if (cell == null && foundConfigs.contains(config)) {
                cell = resultsTable.new Cell(-1, null);
            }
            results = results + printCell(cell);
        }
        results = results + "</tr>" + EOL;
        return results;
    }

    private String printCell(Cell cell) {
        String result = null;
        String displayName = null;
        if (cell == null) {
            displayName = "<td style=\"text-align:center\">&nbsp;</td>";
            result = displayName;
        } else {
            int cellErrorCount = cell.getErrorCount();
            File cellResultsFile = cell.getResultsFile();
            String filename = null;
            int beginFilename = 0;
            String rawfilename = null;
            if (cellResultsFile != null) {
                filename = cellResultsFile.getName();
                beginFilename = filename.lastIndexOf(File.separatorChar);
                rawfilename = filename.substring(beginFilename + 1, filename.length() - XML_EXTENSION.length());
            }
            String startCell = null;
            if (cellErrorCount == -999) {
                displayName = "<td style=\"text-align:center\">&nbsp;</td>";
                result = displayName;
            } else if (cellErrorCount == 0) {
                startCell = "<td style=\"text-align:center\">";
                displayName = "(0)";
                result = addLinks(startCell, displayName, rawfilename);
            } else if (cellErrorCount < 0) {
                startCell = "<td style=\"text-align:center; color: #FF0000;\">";
                displayName = "(" + Integer.toString(cellErrorCount) + ") DNF ";
                result = startCell + displayName + "</td>";
            } else if (cellErrorCount > 0) {
                startCell = "<td style=\"text-align:center; color: #FF0000;\">";
                displayName = "(" + Integer.toString(cellErrorCount) + ")";
                result = addLinks(startCell, displayName, rawfilename);
            } else {
                // should never occur
                displayName = "<td>?" + Integer.toString(cellErrorCount) + "?</td>";
                result = displayName;
            }
        }
        return result;

    }

    private String addLinks(String startCell, String displayName, String rawfilename) {
        String result = startCell;
        result = result + "<a style=\"color:inherit\" title=\"Detailed Unit Test Results Table\" href=" + "\""
                + hrefTestResultsTargetPath + "/html/" + rawfilename + HTML_EXTENSION + "\">" + displayName + "</a>";
        result = result
                + "<a style=\"color:#555555\" title=\"XML Test Result (e.g. for importing into the Eclipse JUnit view)\" href=\""
                + hrefTestResultsTargetPath + "/xml/" + rawfilename + XML_EXTENSION + "\">&nbsp;(XML)</a>";
        return result + "</td>";
    }

    // Totally non-functional method. restored from history for investigation.
    // I restored this 'mailResults' method from history. It was removed about
    // 3.8 M3. It was commented out
    // at that time. Not sure for how long. I am not sure where "Mailer" class
    // was coming from.
    // Needs more research or re-invention. (Compare with CBI aggregator
    // method?)

    void mailResults() {
        Mailer mailer = null;
        // send a different message for the following cases:
        // build is not tested at all // build is tested, tests have not run
        // build is tested, tests have run with error and or failures
        // build is tested, tests have run with no errors or failures
        try {
            mailer = new Mailer();
        }
        catch (NoClassDefFoundError e) {
            return;
        }
        String buildLabel = mailer.getBuildLabel();
        String httpUrl = mailer.getHttpUrl() + "/" + buildLabel; //

        String subject = "Build is complete.  ";

        String downloadLinks = "\n\nHTTP Download:\n\n\t" + httpUrl + " \n\n"; //

        // provide http links
        String message = "The build is complete." + downloadLinks;

        if (testsRan()) {
            subject = "Automated JUnit testing complete.  ";
            message = "Automated JUnit testing is complete.  ";
            subject = subject
                    .concat((getTestResultsWithProblems().endsWith("\n")) ? "All tests pass." : "Test failures/errors occurred.");
            message = message.concat((getTestResultsWithProblems().endsWith("\n")) ? "All tests pass."
                    : "Test failures/errors occurred in the following:  " + getTestResultsWithProblems()) + downloadLinks;
        } else if (isBuildTested() && (!getBuildType().equals("N"))) {
            subject = subject.concat("Automated JUnit testing is starting.");
            message = "The " + subject + downloadLinks;
        }

        if (subject.endsWith("Test failures/errors occurred.")) {
            mailer.sendMessage(subject, message);
        } else if (!getBuildType().equals("N")) {
            mailer.sendMessage(subject, message);
        }
    }

    private boolean testsRan() {
        return testRan;
    }

    /* purely a place holder */
    class Mailer {

        public Object getBuildProperties() {
            // TODO Auto-generated method stub
            return null;
        }

        public String getBuildLabel() {
            // TODO Auto-generated method stub
            return null;
        }

        public String getHttpUrl() {
            // TODO Auto-generated method stub
            return null;
        }

        public void sendMessage(String subject, String message) {
            // TODO Auto-generated method stub

        }

    }

}
