/*******************************************************************************
 * 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 int getCellCount(String column) {
                Cell cell = row.get(column);
                Integer value = cell.getErrorCount();
                if (value == null) {
                    return -999;
                } else {
                    return value;
                }
            }

            public File getCellFile(String column) {
                Cell cell = row.get(column);
                File value = cell.getResultsFile();
                return value;
            }

            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 static final String testResultsToken               = "%testresults%";

    private ArrayList<String>   foundConfigs                   = new ArrayList();
    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       found_config_type              = "found";
    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              testResultsTemplateString      = "";

    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 index.php file.
    private String              testResultsTemplateFileName;

    // 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/N20160406-2048/testresults/xml");
            test.setHtmlDirectoryName(
                    "/data/shared/eclipse/buildsmirror/4N/siteDir/eclipse/downloads/drops4/N20160406-2048/testresults");
            test.setDropDirectoryName("/data/shared/eclipse/buildsmirror/4N/siteDir/eclipse/downloads/drops4/N20160406-2048");
         //   test.setTestResultsTemplateFileName(
         //           "/home/davidw/gitNeon/eclipse.platform.releng.aggregator/eclipse.platform.releng.tychoeclipsebuilder/eclipse/publishingFiles/templateFiles/testResults.template.php");

            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/N20160406-2048/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.

    // defaults removed 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(testManifestFileName);
        getDropTokensFromList(dropTokenList);
        testResultsTemplateString = ""; //readFile(testResultsTemplateFileName);
        dropTemplateString = readFile(dropTemplateFileName);

        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;
        }

        final String hrefCompileLogsTargetPath2 = getHrefCompileLogsTargetPath();
        final int i = fileName.indexOf(hrefCompileLogsTargetPath2);

        final String shortName = fileName.substring(i + hrefCompileLogsTargetPath2.length());

        buffer.append("<tr>\n<td>\n").append("<a href=").append("\"").append(hrefCompileLogsTargetPath2).append(shortName)
                .append("\">").append(shortName).append("</a>").append("</td>\n").append("<td align=\"center\">").append("<a href=")
                .append("\"").append(hrefCompileLogsTargetPath2).append(shortName).append("#FORBIDDEN_WARNINGS").append("\">")
                .append(forbiddenAccessesWarningsCount).append("</a>").append("</td>\n").append("<td align=\"center\">")
                .append("<a href=").append("\"").append(hrefCompileLogsTargetPath2).append(shortName)
                .append("#DISCOURAGED_WARNINGS").append("\">").append(discouragedAccessesWarningsCount).append("</a>")
                .append("</td>\n").append("</tr>\n");
    }

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

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

        final String hrefCompileLogsTargetPath2 = getHrefCompileLogsTargetPath();
        final int i = fileName.indexOf(hrefCompileLogsTargetPath2);

        final String shortName = fileName.substring(i + hrefCompileLogsTargetPath2.length());

        buffer.append("<tr>\n<td>\n").append("<a href=").append("\"").append(hrefCompileLogsTargetPath2).append(shortName)
                .append("\">").append(shortName).append("</a>").append("</td>\n").append("<td align=\"center\">").append("<a href=")
                .append("\"").append(hrefCompileLogsTargetPath2).append(shortName).append("#ERRORS").append("\">")
                .append(errorCount).append("</a>").append("</td>\n").append("<td align=\"center\">").append("<a href=").append("\"")
                .append(hrefCompileLogsTargetPath2).append(shortName).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;
    }

    public String getTestResultsTemplateFileName() {
        return testResultsTemplateFileName;
    }

    /**
     * @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);
        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></td><td></td></tr>");
            }
            if (accessesString.length() == 0) {
                accessesString.append("<tr><td>None</td><td></td><td></td></tr>");
            }

            compileLogResults = "        <div class=\"homeitem3col\">" + EOL
                    + "<h3 id=\"PluginsErrors\">Plugins containing compile errors or warnings</h3>" + EOL
                    + "&nbsp;&nbsp;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." + EOL + "<br /><br />" + EOL + "<table width=\"90%\" border=\"1\">" + EOL + "  <tr>"
                    + EOL + "    <th>Compile Logs (Jar Files)</th>" + EOL + "    <th>Errors</th>" + EOL + "    <th>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 width=\"90%\" border=\"1\">" + EOL + " <tr>" + EOL + "    <th>Compile Logs (Jar Files)</th>" + EOL
                    + "   <th>Forbidden Access Warnings</th>" + EOL + "   <th>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: Generating test results index page");
        log("Parsing XML JUnit results files");
        String replaceString = "";
        final File sourceDirectory = new File(xmlDirectoryName);
        File[] xmlFileNames = null;
        ResultsTable resultsTable = new ResultsTable(getTestsConfig());
        if (sourceDirectory.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 = sourceDirectory.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);
                    }
                }
            }
            xmlFileNames = new File[allFileNames.size()];
            allFileNames.toArray(xmlFileNames);
            // log("DEBUG: Found " + xmlFileNames.length + " XML test results
            // files total.");
            // 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);
                String fullName = junitResultsFile.getPath();
                int errorCount = countErrors(fullName);
                resultsTable.putCell(computeCoreName(junitResultsFile), computeConfig(junitResultsFile), errorCount,
                        junitResultsFile);
                if (errorCount != 0) {
                    trackDataForMail(sourceDirectoryCanonicalPath, junitResultsFile, fullName);
                }
            }
            // above is all "compute data".
            // now time to "display" it.
            for (String row : resultsTable) {
                // File junitResultsFile = xmlFileNames[i];
                replaceString = replaceString + formatJUnitRow(row, resultsTable);
            }
            // System.out.println("Debug: results: " + replaceString);
        } else {
            // error? Or, just too early?
            log("WARNING: sourceDirectory did not exist at \n\t" + sourceDirectory);
            log("     either incorrect call to 'generate index' or called too early (tests not done yet)?");
        }

        // WRITE
        // String tmp = formatJUnitTable(xmlFileNames, resultsTable);
        // replaceString = replaceString + tmp;

        // check for missing test logs
        replaceString = replaceString + verifyAllTestsRan(xmlDirectoryName);

        replaceString = replaceString + listMissingManifestFiles();

        if (foundConfigs.size() > 0) {
           // testResultsTemplateString = replace(testResultsTemplateString, testResultsToken, replaceString);
            testResultsTemplateString = replaceString;
            setTestsRan(true);
            // write each to output directory in file testConfigs.php
            writePhpConfigFile(sourceDirectory, found_config_type, foundConfigs, FOUND_TEST_CONFIGS_FILENAME);
        } else {
            setTestsRan(false);
            log("Test results not found in " + sourceDirectory.getAbsolutePath());
        }
        writeTestResultsFile();
    }

    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) {
        if (doMissingList) {
            if (!verifyLogInManifest(junitResultsFile.getName())) {
                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(final File sourceDirectory, 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 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;
    }

    public void setTestResultsTemplateFileName(final String aString) {
        testResultsTemplateFileName = 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) {
        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 width=\"65%\" border=\"1\" bgcolor=\"#EEEEEE\" rules=\"groups\" align=\"center\">"
                    + "<tr bgcolor=\"#9999CC\"> <th width=\"80%\" 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
                }
            }
        }
    }

    private void writeTestResultsFile() {
        final String outputFileName = dropDirectoryName + File.separator + testResultsHtmlFileName;
        writeFile(outputFileName, testResultsTemplateString);
        log("End: Generating test results index page");
    }

    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.
            final File sourceDirectory = new File(xmlDirectoryName);
            writePhpConfigFile(sourceDirectory, 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) {
        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 width=\"65%\" border=\"1\" bgcolor=\"#EEEEEE\" rules=\"groups\" align=\"center\">"
                        + "<tr bgcolor=\"#9999CC\"> <th width=\"80%\" align=\"center\">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) throws IOException {

        String results = "";
        // String fileName = xmlResultsFile.getPath();

        // for (String config : getTestsConfig()) {
        // Integer cellResult = resultsTable.getCell(corename, config);

        // For brevity, get org.eclipse. out of the component name
        // "org.eclipse." is 12, 13 was hard coded?
        int orgEclipseLength = "org.eclipse.".length();
        // indexOf('_') assumes never part of file name?
        final String shortName = corename.substring(orgEclipseLength);
        String displayName = "o.e." + shortName;

        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 + "<td align=\"center\">" + printCell(cell) + "</td>";
        }
        results = results + "</tr>" + EOL;
        return results;
    }

    private String printCell(Cell cell) {
        String result = null;
        String displayName = null;
        if (cell == null) {
            displayName = "&nbsp;";
            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());
            }

            if (cellErrorCount == -999) {
                displayName = "&nbsp;";
                result = displayName;
            } else if (cellErrorCount == 0) {
                displayName = "(0)";
                result = addLinks(displayName, rawfilename);
            } else if (cellErrorCount < 0) {
                displayName = "<font color=\"#ff0000\">(" + Integer.toString(cellErrorCount) + ") DNF </font>";
                result = displayName;
            } else if (cellErrorCount > 0) {
                displayName = "<font color=\"#ff0000\">(" + Integer.toString(cellErrorCount) + ")</font>";
                result = addLinks(displayName, rawfilename);
            } else {
                displayName = "?" + Integer.toString(cellErrorCount) + "?";
                result = displayName;
            }
        }
        return result;

    }

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

    // 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

        }

    }

}
