diff --git a/Tasks/ANT/anttask.ts b/Tasks/ANT/anttask.ts
index e9638ff74332..bb0befd973a1 100644
--- a/Tasks/ANT/anttask.ts
+++ b/Tasks/ANT/anttask.ts
@@ -4,6 +4,8 @@ import tl = require('vsts-task-lib/task');
 import path = require('path');
 import fs = require('fs');
 import os = require('os');
+import * as Q from "q";
+import {CodeCoverageEnablerFactory} from 'codecoverage-tools/codecoveragefactory';
 
 var isWindows = os.type().match(/^Win/);
 
@@ -78,25 +80,45 @@ function processAntOutputLine(line) {
 
 async function doWork() {
 
-    function enableCodeCoverage() {
+    function execEnableCodeCoverage(): Q.Promise<string> {
+        return enableCodeCoverage()
+            .then(function (resp) {
+                tl.debug("Enabled code coverage successfully");
+                return "CodeCoverage_9064e1d0";
+            }).catch(function (err) {
+                tl.warning("Failed to enable code coverage: " + err);
+                return "";
+            });
+    };
+
+    function enableCodeCoverage(): Q.Promise<any> {
+        if (!isCodeCoverageOpted) {
+            return Q.resolve(true);
+        }
+
         var classFilter: string = tl.getInput('classFilter');
         var classFilesDirectories: string = tl.getInput('classFilesDirectories', true);
         var sourceDirectories: string = tl.getInput('srcDirectories');
         // appending with small guid to keep it unique. Avoiding full guid to ensure no long path issues.
         var reportDirectoryName = "CCReport43F6D5EF";
         reportDirectory = path.join(buildRootPath, reportDirectoryName);
-        ccReportTask = "CodeCoverage_9064e1d0";
         var reportBuildFileName = "CCReportBuildA4D283EG.xml";
         reportBuildFile = path.join(buildRootPath, reportBuildFileName);
         var summaryFileName = "coverage.xml";
         summaryFile = path.join(buildRootPath, reportDirectoryName);
         summaryFile = path.join(summaryFile, summaryFileName);
         var coberturaCCFile = path.join(buildRootPath, "cobertura.ser");
+        var instrumentedClassesDirectory = path.join(buildRootPath, "InstrumentedClasses");
 
         // clean any previous reports.
-        tl.rmRF(coberturaCCFile, true);
-        tl.rmRF(reportDirectory, true);
-        tl.rmRF(reportBuildFile, true);
+        try {
+            tl.rmRF(coberturaCCFile, true);
+            tl.rmRF(reportDirectory, true);
+            tl.rmRF(reportBuildFile, true);
+            tl.rmRF(instrumentedClassesDirectory, true);
+        } catch (err) {
+            tl.debug("Error removing previous cc files: " + err);
+        }
 
         var buildProps: { [key: string]: string } = {};
         buildProps['buildfile'] = antBuildFile;
@@ -105,20 +127,15 @@ async function doWork() {
         buildProps['sourcedirectories'] = sourceDirectories;
         buildProps['summaryfile'] = summaryFileName;
         buildProps['reportdirectory'] = reportDirectory;
-        buildProps['ccreporttask'] = ccReportTask
+        buildProps['ccreporttask'] = "CodeCoverage_9064e1d0"
         buildProps['reportbuildfile'] = reportBuildFile;
-        try {
-            var codeCoverageEnabler = new tl.CodeCoverageEnabler('Ant', ccTool);
-            codeCoverageEnabler.enableCodeCoverage(buildProps);
-            tl.debug("Code coverage is successfully enabled.");
-        }
-        catch (Error) {
-            tl.warning("Enabling code coverage failed. Check the build logs for errors.");
-        }
+
+        let ccEnabler = new CodeCoverageEnablerFactory().getTool("ant", ccTool.toLowerCase());
+        return ccEnabler.enableCodeCoverage(buildProps);
     }
 
-    function publishCodeCoverage(codeCoverageOpted: boolean) {
-        if (codeCoverageOpted) {
+    function publishCodeCoverage(codeCoverageOpted: boolean, ccReportTask: string) {
+        if (codeCoverageOpted && ccReportTask) {
             tl.debug("Collecting code coverage reports");
             var antRunner = tl.tool(anttool);
             antRunner.arg('-buildfile');
@@ -208,39 +225,26 @@ async function doWork() {
 
         var ccTool = tl.getInput('codeCoverageTool');
         var isCodeCoverageOpted = (typeof ccTool != "undefined" && ccTool && ccTool.toLowerCase() != 'none');
-
         var buildRootPath = path.dirname(antBuildFile);
-        var instrumentedClassesDirectory = path.join(buildRootPath, "InstrumentedClasses");
-        //delete any previous cobertura instrumented classes as they might interfere with ant execution.
-        tl.rmRF(instrumentedClassesDirectory, true);
-
-        if (isCodeCoverageOpted) {
-            var summaryFile: string = null;
-            var reportDirectory: string = null;
-            var ccReportTask: string = null;
-            var reportBuildFile: string = null;
-            enableCodeCoverage();
-        }
-        else {
-            tl.debug("Option to enable code coverage was not selected and is being skipped.");
-        }
-
+        
+        var summaryFile: string = null;
+        var reportDirectory: string = null;
+        var ccReportTask: string = null;
+        var reportBuildFile: string = null;
         var publishJUnitResults = tl.getInput('publishJUnitResults');
         var testResultsFiles = tl.getInput('testResultsFiles', true);
 
-        await antv.exec();
+        ccReportTask = await execEnableCodeCoverage();
 
+        await antv.exec();
         var buffer;
         antb.on('stdout', (data) => {
             if (data) {
                 buffer += data.toString();
-
                 let idx = buffer.indexOf(os.EOL);
                 while (idx > -1) {
                     let line = buffer.substring(0, idx);
-
                     processAntOutputLine(line);
-
                     buffer = buffer.substring(idx + os.EOL.length);
                     idx = buffer.indexOf(os.EOL);
                 }
@@ -250,11 +254,10 @@ async function doWork() {
         antb.exec()
             .then(function (code) {
                 publishTestResults(publishJUnitResults, testResultsFiles);
-                publishCodeCoverage(isCodeCoverageOpted);
+                publishCodeCoverage(isCodeCoverageOpted, ccReportTask);
                 tl.setResult(tl.TaskResult.Succeeded, "Task succeeded");
             })
             .fail(function (err) {
-                publishTestResults(publishJUnitResults, testResultsFiles);
                 console.error(err.message);
                 tl.debug('taskRunner fail');
                 tl.setResult(tl.TaskResult.Failed, err);
@@ -264,7 +267,6 @@ async function doWork() {
         tl._writeError(e);
         tl.setResult(tl.TaskResult.Failed, e.message);
     }
-
 }
 
 doWork();
diff --git a/Tasks/ANT/package.json b/Tasks/ANT/package.json
index 4d02da0f4c94..5239b0521415 100644
--- a/Tasks/ANT/package.json
+++ b/Tasks/ANT/package.json
@@ -7,6 +7,7 @@
     "url": "https://github.com/Microsoft/vso-agent-tasks/issues"
   },
   "dependencies": {
+    "xml2js": "^0.4.16",
     "vsts-task-lib": "0.9.7"
   }
 }
diff --git a/Tasks/ANT/task.json b/Tasks/ANT/task.json
index 483d3ce69cc2..5238c0035292 100644
--- a/Tasks/ANT/task.json
+++ b/Tasks/ANT/task.json
@@ -13,7 +13,7 @@
     "version": {
         "Major": 1,
         "Minor": 0,
-        "Patch": 51
+        "Patch": 54
     },
     "demands": [
         "ant"
diff --git a/Tasks/ANT/task.loc.json b/Tasks/ANT/task.loc.json
index 1d8622a08f42..e0f7d90fc2c8 100644
--- a/Tasks/ANT/task.loc.json
+++ b/Tasks/ANT/task.loc.json
@@ -13,7 +13,7 @@
   "version": {
     "Major": 1,
     "Minor": 0,
-    "Patch": 51
+    "Patch": 54
   },
   "demands": [
     "ant"
diff --git a/Tasks/Common/codecoverage-tools/Strings/resources.resjson/en-US/resources.resjson b/Tasks/Common/codecoverage-tools/Strings/resources.resjson/en-US/resources.resjson
new file mode 100644
index 000000000000..1ad61bc14d8a
--- /dev/null
+++ b/Tasks/Common/codecoverage-tools/Strings/resources.resjson/en-US/resources.resjson
@@ -0,0 +1,5 @@
+{
+  "loc.messages.InvalidBuildFile": "Invalid or unsupported build file",
+  "loc.messages.FileNotFound": "File or folder doesn't exist: %s",
+  "loc.messages.FailedToAppendCC": "Unable to append code coverage data: %s"
+}
\ No newline at end of file
diff --git a/Tasks/Common/codecoverage-tools/cobertura/cobertura.ant.ccenabler.ts b/Tasks/Common/codecoverage-tools/cobertura/cobertura.ant.ccenabler.ts
new file mode 100644
index 000000000000..68d01f3e0cd7
--- /dev/null
+++ b/Tasks/Common/codecoverage-tools/cobertura/cobertura.ant.ccenabler.ts
@@ -0,0 +1,190 @@
+/// <reference path="../../../../definitions/Q.d.ts" />
+/// <reference path="../../../../definitions/string.d.ts" />
+/// <reference path="../../../../definitions/vsts-task-lib.d.ts" />
+/// <reference path="../../../../definitions/node.d.ts" />
+
+import * as Q from "q";
+import * as util from "../utilities";
+import * as tl from "vsts-task-lib/task";
+import * as ccc from "../codecoverageconstants";
+import * as cc from "../codecoverageenabler";
+import * as str from "string";
+import * as path from "path";
+
+export class CoberturaAntCodeCoverageEnabler extends cc.CoberturaCodeCoverageEnabler {
+
+    reportDir: string;
+    reportbuildfile: string;
+    classDirs: string;
+    includeFilter: string;
+    excludeFilter: string;
+    sourceDirs: string;
+
+    // -----------------------------------------------------
+    // Enable code coverage for Cobertura Ant Builds
+    // - enableCodeCoverage: CodeCoverageProperties  - ccProps
+    // -----------------------------------------------------    
+    public enableCodeCoverage(ccProps: { [name: string]: string }): Q.Promise<boolean> {
+        let _this = this;
+
+        tl.debug("Input parameters: " + JSON.stringify(ccProps));
+
+        _this.reportDir = "CCReport43F6D5EF";
+        _this.reportbuildfile = "CCReportBuildA4D283EG.xml";
+        _this.buildFile = ccProps["buildfile"];
+        let classFilter = ccProps["classfilter"];
+        let srcDirs = ccProps["sourcedirectories"];
+        if (str(srcDirs).isEmpty()) {
+            srcDirs = ".";
+        }
+        _this.sourceDirs = srcDirs;
+        _this.classDirs = ccProps["classfilesdirectories"];
+
+        let filter = _this.extractFilters(classFilter);
+        _this.excludeFilter = _this.applyFilterPattern(filter.excludeFilter).join(",");
+        _this.includeFilter = _this.applyFilterPattern(filter.includeFilter).join(",");
+
+        tl.debug("Reading the build file: " + _this.buildFile);
+
+        return util.readXmlFileAsJson(_this.buildFile)
+            .then(function (resp) {
+                return _this.addCodeCoverageData(resp);
+            })
+            .thenResolve(true);
+    }
+
+    protected applyFilterPattern(filter: string): string[] {
+        let ccfilter = [];
+
+        if (!util.isNullOrWhitespace(filter)) {
+            str(util.trimToEmptyString(filter)).replaceAll(".", "/").s.split(":").forEach(exFilter => {
+                if (exFilter) {
+                    ccfilter.push(str(exFilter).endsWith("*") ? ("**/" + exFilter + "/**") : ("**/" + exFilter + ".class"));
+                }
+            });
+        }
+
+        tl.debug("Applying the filter pattern: " + filter + " op: " + ccfilter);
+        return ccfilter;
+    }
+
+    protected getClassData(): any {
+        let _this = this;
+        let fileset = [];
+        let classDirs = _this.classDirs;
+
+        if (str(classDirs).isEmpty()) {
+            classDirs = ".";
+        }
+        classDirs.split(",").forEach(cdir => {
+            let filter = {
+                $: {
+                    dir: cdir,
+                    includes: _this.includeFilter,
+                    excludes: _this.excludeFilter
+                }
+            };
+            fileset.push(filter);
+        });
+        return fileset;
+    }
+
+    protected createReportFile(reportContent: string): Q.Promise<void> {
+        let _this = this;
+        tl.debug("Creating the report file: " + _this.reportbuildfile);
+
+        let reportFile = path.join(path.dirname(_this.buildFile), _this.reportbuildfile);
+        return util.writeFile(reportFile, reportContent);
+    }
+
+    protected addCodeCoverageData(pomJson: any): Q.Promise<any[]> {
+        let _this = this;
+
+        if (!pomJson || !pomJson.project) {
+            return Q.reject<any>(tl.loc("InvalidBuildFile"));
+        }
+
+        let reportPluginData = ccc.coberturaAntReport(_this.sourceDirs, path.join(path.dirname(_this.buildFile), _this.reportDir));
+        return Q.all([_this.addCodeCoverageNodes(pomJson), _this.createReportFile(reportPluginData)]);
+    }
+
+    protected addCodeCoverageNodes(buildJsonContent: any): Q.Promise<any> {
+        let _this = this;
+
+        if (!buildJsonContent.project.target) {
+            tl.debug("Build tag is not present");
+            return Q.reject(tl.loc("InvalidBuildFile"));
+        }
+
+        ccc.coberturaAntCoverageEnable(buildJsonContent.project);
+
+        if (!buildJsonContent.project.target || typeof buildJsonContent.project.target === "string") {
+            buildJsonContent.project.target = {};
+        }
+
+        if (buildJsonContent.project.target instanceof Array) {
+            buildJsonContent.project.target.forEach(element => {
+                _this.enableForking(element);
+            });
+        } else {
+            _this.enableForking(buildJsonContent.project.target);
+        }
+        return util.writeJsonAsXmlFile(_this.buildFile, buildJsonContent);
+    }
+
+    protected enableForking(targetNode: any) {
+        let _this = this;
+        let coberturaNode = ccc.coberturaAntInstrumentedClasses(path.dirname(_this.buildFile), _this.reportDir);
+        coberturaNode.fileset = _this.getClassData();
+        let testNodes = ["junit", "java", "testng", "batchtest"];
+
+        if (targetNode.javac) {
+            if (targetNode.javac instanceof Array) {
+                targetNode.javac.forEach(jn => {
+                    jn.$.debug = "true";
+                });
+            }
+        }
+
+        testNodes.forEach(tn => {
+            if (!targetNode[tn]) {
+                return;
+            }
+
+            let node = targetNode[tn];
+            _this.enableForkOnTestNodes(node, true);
+            if (node instanceof Array) {
+                node.forEach(n => {
+                    ccc.coberturaAntProperties(n, _this.reportDir, path.dirname(_this.buildFile));
+                });
+            } else {
+                ccc.coberturaAntProperties(node, _this.reportDir, path.dirname(_this.buildFile));
+            }
+
+            targetNode["cobertura-instrument"] = coberturaNode;
+        });
+    }
+
+    protected enableForkOnTestNodes(testNode: any, enableForkMode: boolean) {
+        if (testNode instanceof Array) {
+            testNode.forEach(element => {
+                if (!element.$) {
+                    element.$ = {};
+                }
+                if (enableForkMode) {
+                    element.$.forkmode = "once";
+                }
+                element.$.fork = "true";
+
+            });
+        } else {
+            if (!testNode.$) {
+                testNode.$ = {};
+            }
+            if (enableForkMode) {
+                testNode.$.forkmode = "once";
+            }
+            testNode.$.fork = "true";
+        }
+    }
+}
diff --git a/Tasks/Common/codecoverage-tools/cobertura/cobertura.gradle.ccenabler.ts b/Tasks/Common/codecoverage-tools/cobertura/cobertura.gradle.ccenabler.ts
new file mode 100644
index 000000000000..259310c2e754
--- /dev/null
+++ b/Tasks/Common/codecoverage-tools/cobertura/cobertura.gradle.ccenabler.ts
@@ -0,0 +1,64 @@
+/// <reference path="../../../../definitions/Q.d.ts" />
+/// <reference path="../../../../definitions/string.d.ts" />
+/// <reference path="../../../../definitions/vsts-task-lib.d.ts" />
+/// <reference path="../../../../definitions/node.d.ts" />
+
+import * as util from "../utilities";
+import * as tl from "vsts-task-lib/task";
+import * as ccc from "../codecoverageconstants";
+import * as cc from "../codecoverageenabler";
+import * as str from "string";
+import * as Q from "q";
+
+export class CoberturaGradleCodeCoverageEnabler extends cc.CoberturaCodeCoverageEnabler {
+    // -----------------------------------------------------
+    // Enable code coverage for Cobertura Gradle Builds
+    // - enableCodeCoverage: CodeCoverageProperties  - ccProps
+    // -----------------------------------------------------    
+    public enableCodeCoverage(ccProps: { [name: string]: string }): Q.Promise<boolean> {
+        let _this = this;
+
+        tl.debug("Input parameters: " + JSON.stringify(ccProps));
+
+        _this.buildFile = ccProps["buildfile"];
+        let classFilter = ccProps["classfilter"];
+        let isMultiModule = ccProps["ismultimodule"] && ccProps["ismultimodule"] === "true";
+        let classFileDirs = ccProps["classfilesdirectories"];
+        let reportDir = ccProps["reportdirectory"];
+        let codeCoveragePluginData = null;
+
+        let filter = _this.extractFilters(classFilter);
+        let cobExclude = _this.applyFilterPattern(filter.excludeFilter);
+        let cobInclude = _this.applyFilterPattern(filter.includeFilter);
+
+        if (isMultiModule) {
+            codeCoveragePluginData = ccc.coberturaGradleMultiModuleEnable(cobExclude.join(","), cobInclude.join(","), classFileDirs, null, reportDir);
+        } else {
+            codeCoveragePluginData = ccc.coberturaGradleSingleModuleEnable(cobExclude.join(","), cobInclude.join(","), classFileDirs, null, reportDir);
+        }
+
+        try {
+            tl.debug("Code Coverage data will be appeneded to build file: " + _this.buildFile);
+            util.insertTextToFileSync(_this.buildFile, ccc.coberturaGradleBuildScript, codeCoveragePluginData);
+            tl.debug("Appended code coverage data");
+        } catch (error) {
+            return Q.reject<boolean>(error);
+        }
+        return Q.resolve(true);
+    }
+
+    protected applyFilterPattern(filter: string): string[] {
+        let ccfilter = [];
+
+        if (!util.isNullOrWhitespace(filter)) {
+            util.trimToEmptyString(filter).split(":").forEach(exFilter => {
+                if (exFilter) {
+                    ccfilter.push(str(exFilter).endsWith("*") ? ("'.*" + util.trimEnd(exFilter, "*") + ".*'") : ("'.*" + exFilter + "'"));
+                }
+            });
+        }
+
+        tl.debug("Applying the filter pattern: " + filter + " op: " + ccfilter);
+        return ccfilter;
+    }
+}
diff --git a/Tasks/Common/codecoverage-tools/cobertura/cobertura.maven.ccenabler.ts b/Tasks/Common/codecoverage-tools/cobertura/cobertura.maven.ccenabler.ts
new file mode 100644
index 000000000000..70941d1f33c4
--- /dev/null
+++ b/Tasks/Common/codecoverage-tools/cobertura/cobertura.maven.ccenabler.ts
@@ -0,0 +1,143 @@
+/// <reference path="../../../../definitions/Q.d.ts" />
+/// <reference path="../../../../definitions/string.d.ts" />
+/// <reference path="../../../../definitions/vsts-task-lib.d.ts" />
+/// <reference path="../../../../definitions/node.d.ts" />
+
+import * as util from "../utilities";
+import * as tl from "vsts-task-lib/task";
+import * as ccc from "../codecoverageconstants";
+import * as cc from "../codecoverageenabler";
+import * as str from "string";
+import * as Q from "q";
+
+export class CoberturaMavenCodeCoverageEnabler extends cc.CoberturaCodeCoverageEnabler {
+
+    protected includeFilter: string;
+    protected excludeFilter: string;
+    // -----------------------------------------------------
+    // Enable code coverage for Cobertura Maven Builds
+    // - enableCodeCoverage: CodeCoverageProperties  - ccProps
+    // -----------------------------------------------------    
+    public enableCodeCoverage(ccProps: { [name: string]: string }): Q.Promise<boolean> {
+        let _this = this;
+
+        tl.debug("Input parameters: " + JSON.stringify(ccProps));
+
+        _this.buildFile = ccProps["buildfile"];
+        let classFilter = ccProps["classfilter"];
+
+        let filter = _this.extractFilters(classFilter);
+        _this.excludeFilter = _this.applyFilterPattern(filter.excludeFilter).join(",");
+        _this.includeFilter = _this.applyFilterPattern(filter.includeFilter).join(",");
+
+        return util.readXmlFileAsJson(_this.buildFile)
+            .then(function (resp) {
+                tl.debug("Read XML: " + resp);
+                return _this.addCodeCoveragePluginData(resp);
+            })
+            .thenResolve(true);
+    }
+
+    protected applyFilterPattern(filter: string): string[] {
+        let ccfilter = [];
+
+        if (!util.isNullOrWhitespace(filter)) {
+            str(util.trimToEmptyString(filter)).replaceAll(".", "/").s.split(":").forEach(exFilter => {
+                if (exFilter) {
+                    ccfilter.push(str(exFilter).endsWith("*") ? (exFilter + "/**") : (exFilter + ".class"));
+                }
+            });
+        }
+
+        tl.debug("Applying the filter pattern: " + filter + " op: " + ccfilter);
+        return ccfilter;
+    }
+
+    protected addCodeCoverageNodes(buildJsonContent: any): Q.Promise<any> {
+        let _this = this;
+        let isMultiModule = false;
+
+        if (!buildJsonContent.project) {
+            return Q.reject(tl.loc("InvalidBuildFile"));
+        }
+
+        if (buildJsonContent.project.modules) {
+            tl.debug("Multimodule project detected");
+            isMultiModule = true;
+        }
+
+        if (!buildJsonContent.project.build) {
+            tl.debug("Build tag is not present");
+            buildJsonContent.project.build = {};
+        }
+
+        let buildNode = _this.getBuildDataNode(buildJsonContent);
+        let pluginsNode = _this.getPluginDataNode(buildNode);
+        let ccPluginData = ccc.coberturaMavenEnable(_this.includeFilter, _this.excludeFilter, String(isMultiModule));
+        let reportContent = ccc.coberturaMavenReport();
+
+        return Q.allSettled([ccPluginData, reportContent])
+            .then(function (resp) {
+                util.addPropToJson(pluginsNode, "plugin", resp[0].value.plugin);
+                util.addPropToJson(buildJsonContent.project.reporting, "plugins", resp[1].value);
+                tl.debug("Final buildContent: " + buildJsonContent);
+                return Q.resolve(buildJsonContent);
+            });
+    }
+
+    private getBuildDataNode(buildJsonContent: any): any {
+        let buildNode = null;
+        if (!buildJsonContent.project.build || typeof buildJsonContent.project.build === "string") {
+            buildNode = {};
+            buildJsonContent.project.build = buildNode;
+        }
+
+        if (buildJsonContent.project.build instanceof Array) {
+            if (typeof buildJsonContent.project.build[0] === "string") {
+                buildNode = {};
+                buildJsonContent.project.build[0] = buildNode;
+            } else {
+                buildNode = buildJsonContent.project.build[0];
+            }
+        }
+        return buildNode;
+    }
+
+    private getPluginDataNode(buildNode: any): any {
+        let pluginsNode = {};
+        if (buildNode.pluginManagement) {
+            if (typeof buildNode.pluginManagement === "string") {
+                buildNode.pluginManagement = {};
+            }
+            if (buildNode.pluginManagement instanceof Array) {
+                pluginsNode = buildNode.pluginManagement[0].plugins;
+            } else {
+                pluginsNode = buildNode.pluginManagement.plugins;
+            }
+        } else {
+            if (!buildNode.plugins || typeof buildNode.plugins === "string") {
+                buildNode.plugins = {};
+            }
+            if (buildNode.plugins instanceof Array) {
+                if (typeof buildNode.plugins[0] === "string") {
+                    pluginsNode = {};
+                    buildNode.plugins[0] = pluginsNode;
+                } else {
+                    pluginsNode = buildNode.plugins[0];
+                }
+            } else {
+                pluginsNode = buildNode.plugins;
+            }
+        }
+        return pluginsNode;
+    }
+
+    protected addCodeCoveragePluginData(pomJson: any): Q.Promise<void> {
+        let _this = this;
+        tl.debug("Adding coverage plugin data");
+        return _this.addCodeCoverageNodes(pomJson)
+            .then(function (buildContent) {
+                return util.writeJsonAsXmlFile(_this.buildFile, buildContent);
+            });
+    }
+}
diff --git a/Tasks/Common/codecoverage-tools/codecoverageconstants.ts b/Tasks/Common/codecoverage-tools/codecoverageconstants.ts
new file mode 100644
index 000000000000..72fc3804c165
--- /dev/null
+++ b/Tasks/Common/codecoverage-tools/codecoverageconstants.ts
@@ -0,0 +1,513 @@
+/// <reference path="../../../definitions/node.d.ts" />
+/// <reference path="../../../definitions/string.d.ts" />
+
+import * as path from "path";
+import * as util from "./utilities";
+import * as os from "os";
+import * as str from "string";
+
+
+// Enable Jacoco Code Coverage for Gradle builds using this props
+export function jacocoGradleMultiModuleEnable(excludeFilter: string, includeFilter: string, classFileDirectory: string, reportDir: string) {
+    return `
+allprojects {
+    repositories {
+        mavenCentral()
+    }
+
+    apply plugin: 'jacoco'
+}
+
+def jacocoExcludes = [${excludeFilter}]
+def jacocoIncludes = [${includeFilter}]
+
+subprojects {	
+    jacocoTestReport {
+        doFirst {
+            classDirectories = fileTree(dir: "${classFileDirectory}").exclude(jacocoExcludes).include(jacocoIncludes)
+        }
+		
+        reports {
+            html.enabled = true
+            html.destination "\${buildDir}/jacocoHtml"
+            xml.enabled = true    
+            xml.destination "\${buildDir}/summary.xml"
+        }
+    }
+    test {
+        jacoco {
+            append = true
+            destinationFile = file("${reportDir}/jacoco.exec")
+        }
+    }
+}
+
+task jacocoRootReport(type: org.gradle.testing.jacoco.tasks.JacocoReport) {
+    dependsOn = subprojects.test
+    executionData = files(subprojects.jacocoTestReport.executionData)
+    sourceDirectories = files(subprojects.sourceSets.main.allSource.srcDirs)
+    classDirectories = files()
+	
+    doFirst {
+        subprojects.each {
+            if (new File("\${it.sourceSets.main.output.classesDir}").exists()) {
+                logger.info("Class directory exists in sub project: \${it.name}")
+                logger.info("Adding class files \${it.sourceSets.main.output.classesDir}")
+                classDirectories += fileTree(dir: "\${it.sourceSets.main.output.classesDir}", includes: jacocoIncludes, excludes: jacocoExcludes)
+            } else {
+                logger.error("Class directory does not exist in sub project: \${it.name}")
+            }
+        }
+    }
+	
+    reports {
+        html.enabled = true
+        xml.enabled = true    
+        xml.destination "${reportDir}/summary.xml"
+        html.destination "${reportDir}/"
+    }
+}`;
+}
+
+export function jacocoGradleSingleModuleEnable(excludeFilter: string, includeFilter: string, classFileDirectory: string, reportDir: string) {
+    return `
+allprojects {
+    repositories {
+        mavenCentral()
+    }
+
+    apply plugin: 'jacoco'
+}
+
+def jacocoExcludes = [${excludeFilter}]
+def jacocoIncludes = [${includeFilter}]
+	
+jacocoTestReport {
+    doFirst {
+        classDirectories = fileTree(dir: "${classFileDirectory}").exclude(jacocoExcludes).include(jacocoIncludes)
+    }
+		
+    reports {
+        html.enabled = true
+        xml.enabled = true    
+        xml.destination "${reportDir}/summary.xml"
+        html.destination "${reportDir}"
+    }
+}
+	
+test {
+    finalizedBy jacocoTestReport
+    jacoco {
+        append = true
+        destinationFile = file("${reportDir}/jacoco.exec")
+    }
+}`;
+}
+
+
+// Enable Cobertura Code Coverage for Gradle builds using this props
+export function coberturaGradleSingleModuleEnable(excludeFilter: string, includeFilter: string, classDir: string, sourceDir: string, reportDir: string) {
+    if (!classDir) {
+        classDir = "${project.sourceSets.main.output.classesDir}";
+    }
+    if (!sourceDir) {
+        sourceDir = "project.sourceSets.main.java.srcDirs";
+    }
+
+    return `
+allprojects {
+    repositories {
+        mavenCentral()
+    }
+    apply plugin: 'net.saliman.cobertura'
+	
+    dependencies {
+        testCompile 'org.slf4j:slf4j-api:1.7.12'
+    }
+
+    cobertura.coverageIncludes = [${includeFilter}]
+    cobertura.coverageExcludes = [${excludeFilter}]
+}
+
+cobertura {
+    coverageDirs = ["${classDir}"]
+    coverageSourceDirs = ${sourceDir}
+    coverageReportDir = new File('${reportDir}')
+    coverageFormats = ['xml', 'html']
+}`;
+}
+export function coberturaGradleMultiModuleEnable(excludeFilter: string, includeFilter: string, classDir: string, sourceDir: string, reportDir: string) {
+    let data = `
+allprojects {
+    repositories {
+        mavenCentral()
+    }
+    apply plugin: 'net.saliman.cobertura'
+	
+    dependencies {
+        testCompile 'org.slf4j:slf4j-api:1.7.12'
+    }
+
+    cobertura.coverageIncludes = [${includeFilter}]
+    cobertura.coverageExcludes = [${excludeFilter}]
+}
+    
+test {
+    dependsOn = subprojects.test
+}
+
+cobertura {	
+    coverageSourceDirs = []`;
+
+    if (classDir) {
+        data += `
+        coverageDirs = ["${classDir}"]`;
+    } else {
+        data += `
+    rootProject.subprojects.each {
+        coverageDirs << file("\${it.sourceSets.main.output.classesDir}")
+    }`;
+    }
+
+    if (sourceDir) {
+        data += `
+    coverageDirs = ["${sourceDir}"]`;
+    } else {
+        data += `
+    rootProject.subprojects.each {
+        coverageSourceDirs += it.sourceSets.main.java.srcDirs
+    }`;
+    }
+    data += `
+    coverageFormats = [ 'xml', 'html' ]
+    coverageMergeDatafiles = subprojects.collect { new File(it.projectDir, '/build/cobertura/cobertura.ser') }
+    coverageReportDir = new File('${reportDir}')
+}`;
+
+    return data;
+};
+
+// Enable Jacoco Code Coverage for Maven builds using this props
+export function jacocoMavenPluginEnable(includeFilter: string[], excludeFilter: string[], outputDirectory: string): any {
+    let plugin = {
+        "groupId": "org.jacoco",
+        "artifactId": "jacoco-maven-plugin",
+        "version": "0.7.5.201505241946",
+        "configuration": {
+            "destFile": path.join(outputDirectory, "jacoco.exec"),
+            "outputDirectory": outputDirectory,
+            "dataFile": path.join(outputDirectory, "jacoco.exec"),
+            "append": "true",
+            "includes": [{
+                "include": includeFilter,
+            }],
+            "excludes": [{
+                "exclude": excludeFilter
+            }]
+        },
+        "executions": {
+            "execution": [
+                {
+                    "configuration":
+                    {
+                        "includes": [{
+                            "include": "**/*",
+                        }]
+                    },
+                    "id": "default-prepare-agent-vsts",
+                    "goals": { "goal": "prepare-agent" }
+                },
+                {
+                    "id": "default-report-vsts",
+                    "goals": { "goal": "report" },
+                    "phase": "test"
+                }
+            ]
+        }
+    };
+
+    return plugin;
+};
+export function jacocoMavenMultiModuleReport(reportDir: string, srcData: string, classData: string, includeFilter: string, excludeFilter: string): string {
+    let classNode = "";
+    classData.split(",").forEach(c => {
+        classNode += `<fileset dir="${c}"`;
+        if (includeFilter) {
+            classNode += ` includes="${includeFilter}"`;
+        }
+        if (excludeFilter) {
+            classNode += ` excludes="${excludeFilter}"`;
+        }
+        classNode += ` />` + os.EOL;
+    });
+    let srcNode = "";
+    if (str(srcData).isEmpty()) {
+        srcNode = `<fileset dir="." />`;
+    } else {
+        srcData.split(",").forEach(c => {
+            srcNode += `<fileset dir="${c}" />` + os.EOL;
+        });
+    }
+
+    let report = `<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>VstsReport</groupId>
+  <artifactId>VstsReport</artifactId>
+  <version>0.0.1-SNAPSHOT</version>
+  <packaging>pom</packaging>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-antrun-plugin</artifactId>
+        <version>1.8</version>
+        <executions>
+          <execution>
+            <phase>post-integration-test</phase>
+            <goals>
+              <goal>run</goal>
+            </goals>
+            <configuration>
+              <target>
+                <echo message="Generating JaCoCo Reports" />
+                <taskdef name="report" classname="org.jacoco.ant.ReportTask">
+                  <classpath path="{basedir}/target/jacoco-jars/org.jacoco.ant.jar" />
+                </taskdef>
+                <report>
+                  <executiondata>
+                    <file file="${path.join(reportDir, "jacoco.exec")}" />
+                  </executiondata>
+                  <structure name="Jacoco report">
+                    <classfiles>
+                      ${classNode}
+                    </classfiles>
+                    <sourcefiles encoding="UTF-8">
+                      ${srcNode}
+                    </sourcefiles>
+                  </structure>
+                  <html destdir="${reportDir}" />
+                  <xml destfile="${reportDir + path.sep}jacoco.xml" />
+                  <csv destfile="${reportDir + path.sep}report.csv" />
+                </report>
+              </target>
+            </configuration>
+          </execution>
+        </executions>
+        <dependencies>
+          <dependency>
+            <groupId>org.jacoco</groupId>
+            <artifactId>org.jacoco.ant</artifactId>
+            <version>0.7.5.201505241946</version>
+          </dependency>
+        </dependencies>
+      </plugin>
+    </plugins>
+  </build>
+</project>
+    `;
+
+    return report;
+};
+
+// Enable Cobertura Code Coverage for Maven builds using this props
+export function coberturaMavenEnable(includeFilter: string, excludeFilter: string, aggregate: string): Q.Promise<any> {
+    let includeTag = "";
+    let excludeTag = "";
+    if (!str(excludeFilter).isEmpty()) {
+        excludeFilter.split(",").forEach(ex => {
+            excludeTag += `<exclude>${ex}</exclude>` + os.EOL;
+        });
+    }
+    if (!str(includeFilter).isEmpty()) {
+        includeFilter.split(",").forEach(ex => {
+            includeTag += `<include>${ex}</include>` + os.EOL;
+        });
+    }
+
+    let ccProperty = `
+    <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>cobertura-maven-plugin</artifactId>
+        <version>2.7</version>
+        <configuration>
+          <formats>
+            <format>xml</format>
+            <format>html</format>
+          </formats>
+          <instrumentation>
+            <includes>${includeTag}</includes>
+            <excludes>${excludeTag}</excludes>
+          </instrumentation>
+          <aggregate>${aggregate}</aggregate>
+        </configuration>
+        <executions>
+          <execution>
+            <id>package-9af52907-6506-4b87-b16a-9883edee41bc</id>
+            <goals>
+              <goal>cobertura</goal>
+            </goals>
+            <phase>package</phase>
+          </execution>
+        </executions>
+    </plugin>
+  `;
+    return util.convertXmlStringToJson(ccProperty);
+};
+
+export function coberturaMavenReport(): Q.Promise<any> {
+    let ccProperty = `
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>cobertura-maven-plugin</artifactId>
+        <version>2.7</version>
+        <configuration>
+          <formats>
+            <format>xml</format>
+            <format>html</format>
+          </formats>
+        </configuration>
+      </plugin>
+  `;
+    return util.convertXmlStringToJson(ccProperty);
+}
+
+export function jacocoAntReport(reportDir: string, classData: string, sourceData: string): string {
+    return `
+      <?xml version='1.0'?>
+        <project name='JacocoReport'>
+               <target name='CodeCoverage_9064e1d0'>
+                  <jacoco:report xmlns:jacoco='antlib:org.jacoco.ant'>
+                      <executiondata>
+                         <file file='${path.join(reportDir, "jacoco.exec")}'/>
+                      </executiondata>
+                      <structure name = 'Jacoco report'>
+                            <classfiles>${classData}</classfiles>
+                            <sourcefiles>${sourceData}</sourcefiles>
+                      </structure>
+                      <html destdir='${reportDir}' />
+                      <csv destfile='${reportDir + path.sep}summary.csv' />
+                      <xml destfile='${reportDir + path.sep}summary.xml' />
+                  </jacoco:report>
+              </target>
+        </project>
+    `;
+}
+
+export function jacocoAntCoverageEnable(): any {
+    return {
+        $:
+        {
+            "destfile": "jacoco.exec",
+            "append": true,
+            "xlmns:jacoco": "antlib:org.jacoco.ant"
+        }
+    };
+}
+
+export function coberturaAntReport(srcDir: string, reportDir: string): string {
+    return `<?xml version="1.0"?>
+<project name="CoberturaReport">
+  <property environment="env" />
+  <path id="cobertura-classpath" description="classpath for instrumenting classes">
+    <fileset dir="\${env.COBERTURA_HOME}">
+      <include name="cobertura*.jar" />
+      <include name="**/lib/**/*.jar" />
+    </fileset>
+  </path>
+  <taskdef classpathref="cobertura-classpath" resource="tasks.properties" />
+  <target name="CodeCoverage_9064e1d0">
+    <cobertura-report format="html" destdir="${reportDir}" datafile="${reportDir + path.sep}cobertura.ser" srcdir="${srcDir}" />
+    <cobertura-report format="xml" destdir="${reportDir}" datafile="${reportDir + path.sep}cobertura.ser" srcdir="${srcDir}" />
+  </target>
+</project>
+    `;
+}
+
+export function coberturaAntCoverageEnable(buildJsonContent: any): void {
+    let propertyNode = {
+        $: {
+            environment: "env"
+        }
+    };
+    util.addPropToJson(buildJsonContent, "property", propertyNode);
+
+    let pathNode = {
+        $: {
+            id: "cobertura-classpath",
+            description: "classpath for instrumenting classes"
+        },
+        fileset: {
+            $: {
+                dir: "${env.COBERTURA_HOME}"
+            },
+            include: [
+                {
+                    $: {
+                        name: "cobertura*.jar"
+                    }
+                },
+                {
+                    $: {
+                        name: "**/lib/**/*.jar"
+                    }
+                }
+            ]
+        }
+    };
+    util.addPropToJson(buildJsonContent, "path", pathNode);
+
+    let taskdefNode = {
+        $: {
+            classpathref: "cobertura-classpath",
+            resource: "tasks.properties"
+        }
+    };
+    util.addPropToJson(buildJsonContent, "taskdef", taskdefNode);
+}
+
+export function coberturaAntInstrumentedClasses(baseDir: string, reportDir: string): any {
+    let ccProperty = {
+        $: {
+            todir: path.join(baseDir, "InstrumentedClasses"),
+            datafile: path.join(baseDir, reportDir, "cobertura.ser")
+        },
+        fileset: []
+    };
+    return ccProperty;
+}
+
+export function coberturaAntProperties(node: any, reportDir: string, baseDir: string): any {
+    node.sysproperty = {
+        $: {
+            key: "net.sourceforge.cobertura.datafile",
+            file: path.join(baseDir, reportDir, "cobertura.ser")
+        }
+    };
+
+    let classpath = [
+        {
+            $: {
+                location: path.join(baseDir, "InstrumentedClasses"),
+            }
+        }
+    ];
+
+    if (node.classpath && node.classpath instanceof Array) {
+        node.classpath = classpath.concat(node.classpath);
+    } else {
+        node.classpath = classpath;
+    }
+}
+
+// Gradle Coberutra plugin
+export const coberturaGradleBuildScript = `
+buildscript {
+    repositories {
+        mavenCentral()
+    }
+    dependencies {
+        classpath 'net.saliman:gradle-cobertura-plugin:2.2.7'
+    }
+}
+`;
diff --git a/Tasks/Common/codecoverage-tools/codecoverageenabler.ts b/Tasks/Common/codecoverage-tools/codecoverageenabler.ts
new file mode 100644
index 000000000000..55c78c3768f5
--- /dev/null
+++ b/Tasks/Common/codecoverage-tools/codecoverageenabler.ts
@@ -0,0 +1,79 @@
+/// <reference path="../../../definitions/Q.d.ts" />
+/// <reference path="../../../definitions/string.d.ts" />
+/// <reference path="../../../definitions/vsts-task-lib.d.ts" />
+/// <reference path="../../../definitions/node.d.ts" />
+
+import * as Q from "q";
+import * as tl from "vsts-task-lib/task";
+import * as util from "./utilities";
+
+// -----------------------------------------------------
+// Interface to be implemented by all code coverage enablers 
+// -----------------------------------------------------
+export interface ICodeCoverageEnabler {
+    // enable code coverage for the given build tool and code coverage tool
+    enableCodeCoverage(ccProps: { [name: string]: string }): Q.Promise<boolean>;
+}
+
+/* Code Coverage enabler for different type of build tools and code coverage tools*/
+export abstract class CodeCoverageEnabler implements ICodeCoverageEnabler {
+    protected buildFile: string;
+
+    abstract enableCodeCoverage(ccProps: { [name: string]: string }): Q.Promise<boolean>;
+
+    // -----------------------------------------------------
+    // Convert the VSTS specific filter to comma seperated specific filter pattern
+    // - +:com.abc,-:com.xy -> com.abc,com.xy
+    // -----------------------------------------------------    
+    protected extractFilters(classFilter: string) {
+        let includeFilter = "";
+        let excludeFilter = "";
+
+        tl.debug("Extracting VSTS filter: " + classFilter);
+        if (util.isNullOrWhitespace(classFilter)) {
+            return {
+                includeFilter: includeFilter,
+                excludeFilter: excludeFilter
+            };
+        }
+
+        classFilter.split(",").forEach(inputFilter => {
+            if (util.isNullOrWhitespace(inputFilter) || inputFilter.length < 2) {
+                throw new Error("Invalid class filter " + inputFilter);
+            }
+
+            switch (inputFilter.charAt(0)) {
+                case "+":
+                    includeFilter += inputFilter.substr(1);
+                    break;
+                case "-":
+                    excludeFilter += inputFilter.substr(1);
+                    break;
+                default:
+                    throw new Error("Invalid class filter " + inputFilter);
+            }
+        });
+
+        tl.debug("Include Filter pattern: " + includeFilter);
+        tl.debug("Exclude Filter pattern: " + excludeFilter);
+
+        return {
+            includeFilter: includeFilter,
+            excludeFilter: excludeFilter
+        };
+    }
+}
+
+export abstract class CoberturaCodeCoverageEnabler extends CodeCoverageEnabler {
+    // -----------------------------------------------------
+    // Convert the VSTS specific filter to Code Coverage Tool specific filter pattern
+    // -----------------------------------------------------   
+    protected abstract applyFilterPattern(filter: string): string[];
+}
+
+export abstract class JacocoCodeCoverageEnabler extends CodeCoverageEnabler {
+    // -----------------------------------------------------
+    // Convert the VSTS specific filter to Code Coverage Tool specific filter pattern
+    // -----------------------------------------------------   
+    protected abstract applyFilterPattern(filter: string): string[];
+}
diff --git a/Tasks/Common/codecoverage-tools/codecoveragefactory.ts b/Tasks/Common/codecoverage-tools/codecoveragefactory.ts
new file mode 100644
index 000000000000..375107a43eb7
--- /dev/null
+++ b/Tasks/Common/codecoverage-tools/codecoveragefactory.ts
@@ -0,0 +1,41 @@
+/// <reference path="../../../definitions/Q.d.ts" />
+/// <reference path="../../../definitions/string.d.ts" />
+/// <reference path="../../../definitions/vsts-task-lib.d.ts" />
+/// <reference path="../../../definitions/node.d.ts" />
+
+import {ICodeCoverageEnabler} from "./codecoverageenabler";
+import {JacocoAntCodeCoverageEnabler} from "./jacoco/jacoco.ant.ccenabler";
+import {JacocoGradleCodeCoverageEnabler} from "./jacoco/jacoco.gradle.ccenabler";
+import {JacocoMavenCodeCoverageEnabler} from "./jacoco/jacoco.maven.ccenabler";
+import {CoberturaAntCodeCoverageEnabler} from "./cobertura/cobertura.ant.ccenabler";
+import {CoberturaMavenCodeCoverageEnabler} from "./cobertura/cobertura.maven.ccenabler";
+import {CoberturaGradleCodeCoverageEnabler} from "./cobertura/cobertura.gradle.ccenabler";
+
+export interface ICodeCoverageEnablerFactory {
+    getTool(buildTool: string, ccTool: string): ICodeCoverageEnabler;
+}
+
+export class CodeCoverageEnablerFactory implements ICodeCoverageEnablerFactory {
+    public getTool(buildTool: string, ccTool: string): ICodeCoverageEnabler {
+        if (!buildTool || !ccTool) {
+            throw new Error("Invalid build tool/code coverage tool");
+        }
+
+        switch (buildTool.toLowerCase() + "-" + ccTool.toLowerCase()) {
+            case "ant-jacoco":
+                return new JacocoAntCodeCoverageEnabler();
+            case "ant-cobertura":
+                return new CoberturaAntCodeCoverageEnabler();
+            case "maven-jacoco":
+                return new JacocoMavenCodeCoverageEnabler();
+            case "maven-cobertura":
+                return new CoberturaMavenCodeCoverageEnabler();
+            case "gradle-jacoco":
+                return new JacocoGradleCodeCoverageEnabler();
+            case "gradle-cobertura":
+                return new CoberturaGradleCodeCoverageEnabler();
+            default:
+                throw new Error("Invalid build tool/code coverage tool");
+        }
+    }
+}
diff --git a/Tasks/Common/codecoverage-tools/jacoco/jacoco.ant.ccenabler.ts b/Tasks/Common/codecoverage-tools/jacoco/jacoco.ant.ccenabler.ts
new file mode 100644
index 000000000000..b9256dd02b7f
--- /dev/null
+++ b/Tasks/Common/codecoverage-tools/jacoco/jacoco.ant.ccenabler.ts
@@ -0,0 +1,195 @@
+/// <reference path="../../../../definitions/Q.d.ts" />
+/// <reference path="../../../../definitions/string.d.ts" />
+/// <reference path="../../../../definitions/vsts-task-lib.d.ts" />
+/// <reference path="../../../../definitions/node.d.ts" />
+
+import * as util from "../utilities";
+import * as tl from "vsts-task-lib/task";
+import * as ccc from "../codecoverageconstants";
+import * as cc from "../codecoverageenabler";
+import * as str from "string";
+import * as os from "os";
+import * as Q from "q";
+
+export class JacocoAntCodeCoverageEnabler extends cc.JacocoCodeCoverageEnabler {
+
+    reportDir: string;
+    excludeFilter: string;
+    includeFilter: string;
+    sourceDirs: string;
+    classDirs: string;
+    reportBuildFile: string;
+
+    // -----------------------------------------------------
+    // Enable code coverage for Jacoco Ant Builds
+    // - enableCodeCoverage: CodeCoverageProperties  - ccProps
+    // -----------------------------------------------------    
+    public enableCodeCoverage(ccProps: { [name: string]: string }): Q.Promise<boolean> {
+        let _this = this;
+
+        tl.debug("Input parameters: " + JSON.stringify(ccProps));
+
+        _this.buildFile = ccProps["buildfile"];
+        _this.sourceDirs = ccProps["sourcedirectories"];
+        _this.classDirs = ccProps["classfilesdirectories"];
+        _this.reportDir = ccProps["reportdirectory"];
+        _this.reportBuildFile = ccProps["reportbuildfile"];
+
+        let classFilter = ccProps["classfilter"];
+        let filter = _this.extractFilters(classFilter);
+        _this.excludeFilter = _this.applyFilterPattern(filter.excludeFilter).join(",");
+        _this.includeFilter = _this.applyFilterPattern(filter.includeFilter).join(",");
+
+        return util.readXmlFileAsJson(_this.buildFile)
+            .then(function (resp) {
+                return _this.addCodeCoverageData(resp);
+            })
+            .thenResolve(true);
+    }
+
+    protected applyFilterPattern(filter: string): string[] {
+        let ccfilter = [];
+
+        if (!util.isNullOrWhitespace(filter)) {
+            str(util.trimToEmptyString(filter)).replaceAll(".", "/").s.split(":").forEach(exFilter => {
+                if (exFilter) {
+                    ccfilter.push(str(exFilter).endsWith("*") ? ("**/" + exFilter + "/**") : ("**/" + exFilter + ".class"));
+                }
+            });
+        }
+
+        tl.debug("Applying the filter pattern: " + filter + " op: " + ccfilter);
+        return ccfilter;
+    }
+
+    protected getSourceFilter(): string {
+        let srcData = "";
+        this.sourceDirs.split(",").forEach(dir => {
+            if (!str(dir).isEmpty()) {
+                srcData += `<fileset dir='${dir}'/>`;
+                srcData += os.EOL;
+            }
+        });
+        if (str(srcData).isEmpty()) {
+            srcData = `<fileset dir='.'/>`;
+            srcData += os.EOL;
+        }
+        return srcData;
+    }
+
+    protected getClassData(): string {
+        let classData = "";
+        this.classDirs.split(",").forEach(dir => {
+            classData += `<fileset dir='${dir}' includes="${this.includeFilter}"  excludes="${this.excludeFilter}" />`;
+            classData += os.EOL;
+        });
+        if (str(classData).isEmpty()) {
+            classData += `<fileset dir='.'${this.includeFilter} ${this.excludeFilter} />`;
+            classData += os.EOL;
+        }
+        return classData;
+    }
+
+    protected createReportFile(reportContent: string): Q.Promise<void> {
+        let _this = this;
+        return util.writeFile(_this.reportBuildFile, reportContent);
+    }
+
+    protected addCodeCoverageData(pomJson: any): Q.Promise<any[]> {
+        let _this = this;
+        if (!pomJson.project) {
+            Q.reject(tl.loc("InvalidBuildFile"));
+        }
+
+        let sourceData = _this.getSourceFilter();
+        let classData = _this.getClassData();
+        let reportPluginData = ccc.jacocoAntReport(_this.reportDir, classData, sourceData);
+
+        return Q.all([_this.addCodeCoveragePluginData(pomJson), _this.createReportFile(reportPluginData)]);
+    }
+
+    protected addCodeCoverageNodes(buildJsonContent: any): Q.Promise<any> {
+        let _this = this;
+
+        if (!buildJsonContent.project.target) {
+            tl.debug("Build tag is not present");
+            return Q.reject(tl.loc("InvalidBuildFile"));
+        }
+
+        if (!buildJsonContent.project.target || typeof buildJsonContent.project.target === "string") {
+            buildJsonContent.project.target = {};
+        }
+
+        if (buildJsonContent.project.target instanceof Array) {
+            buildJsonContent.project.target.forEach(element => {
+                _this.enableForking(element);
+            });
+        } else {
+            _this.enableForking(buildJsonContent.project.target);
+        }
+
+        return Q.resolve(buildJsonContent);
+    }
+
+    protected enableForking(targetNode: any) {
+        let _this = this;
+        let testNodes = ["junit", "java", "testng", "batchtest"];
+        let coverageNode = ccc.jacocoAntCoverageEnable();
+
+        if (!str(_this.includeFilter).isEmpty()) {
+            coverageNode.$.includes = _this.includeFilter;
+        }
+        if (!str(_this.excludeFilter).isEmpty()) {
+            coverageNode.$.excludes = _this.excludeFilter;
+        }
+
+        if (targetNode.javac) {
+            if (targetNode.javac instanceof Array) {
+                targetNode.javac.forEach(jn => {
+                    jn.$.debug = "true";
+                });
+            }
+        }
+
+        testNodes.forEach(tn => {
+            if (!targetNode[tn]) {
+                return;
+            }
+            _this.enableForkOnTestNodes(targetNode[tn], true);
+            coverageNode[tn] = targetNode[tn];
+            delete targetNode[tn];
+            targetNode["jacoco:coverage"] = coverageNode;
+        });
+    }
+
+    protected enableForkOnTestNodes(testNode: any, enableForkMode: boolean) {
+        if (testNode instanceof Array) {
+            testNode.forEach(element => {
+                if (!element.$) {
+                    element.$ = {};
+                }
+                if (enableForkMode) {
+                    element.$.forkmode = "once";
+                }
+                element.$.fork = "true";
+
+            });
+        } else {
+            if (!testNode.$) {
+                testNode.$ = {};
+            }
+            if (enableForkMode) {
+                testNode.$.forkmode = "once";
+            }
+            testNode.$.fork = "true";
+        }
+    }
+
+    protected addCodeCoveragePluginData(pomJson: any): Q.Promise<any> {
+        let _this = this;
+        return _this.addCodeCoverageNodes(pomJson)
+            .then(function (content) {
+                return util.writeJsonAsXmlFile(_this.buildFile, content);
+            });
+    }
+}
diff --git a/Tasks/Common/codecoverage-tools/jacoco/jacoco.gradle.ccenabler.ts b/Tasks/Common/codecoverage-tools/jacoco/jacoco.gradle.ccenabler.ts
new file mode 100644
index 000000000000..c4f0cff0f186
--- /dev/null
+++ b/Tasks/Common/codecoverage-tools/jacoco/jacoco.gradle.ccenabler.ts
@@ -0,0 +1,65 @@
+/// <reference path="../../../../definitions/Q.d.ts" />
+/// <reference path="../../../../definitions/string.d.ts" />
+/// <reference path="../../../../definitions/vsts-task-lib.d.ts" />
+/// <reference path="../../../../definitions/node.d.ts" />
+
+import * as util from "../utilities";
+import * as tl from "vsts-task-lib/task";
+import * as ccc from "../codecoverageconstants";
+import * as cc from "../codecoverageenabler";
+import * as str from "string";
+import * as Q from "q";
+
+export class JacocoGradleCodeCoverageEnabler extends cc.JacocoCodeCoverageEnabler {
+    // -----------------------------------------------------
+    // Enable code coverage for Jacoco Gradle Builds
+    // - enableCodeCoverage: CodeCoverageProperties  - ccProps
+    // -----------------------------------------------------    
+    public enableCodeCoverage(ccProps: { [name: string]: string }): Q.Promise<boolean> {
+        let _this = this;
+
+        tl.debug("Input parameters: " + JSON.stringify(ccProps));
+
+        _this.buildFile = ccProps["buildfile"];
+        let classFilter = ccProps["classfilter"];
+        let isMultiModule = ccProps["ismultimodule"] && ccProps["ismultimodule"] === "true";
+        let classFileDirs = ccProps["classfilesdirectories"];
+        let reportDir = ccProps["reportdirectory"];
+        let codeCoveragePluginData = null;
+
+        let filter = _this.extractFilters(classFilter);
+        let jacocoExclude = _this.applyFilterPattern(filter.excludeFilter);
+        let jacocoInclude = _this.applyFilterPattern(filter.includeFilter);
+
+        if (isMultiModule) {
+            codeCoveragePluginData = ccc.jacocoGradleMultiModuleEnable(jacocoExclude.join(","), jacocoInclude.join(","), classFileDirs, reportDir);
+        } else {
+            codeCoveragePluginData = ccc.jacocoGradleSingleModuleEnable(jacocoExclude.join(","), jacocoInclude.join(","), classFileDirs, reportDir);
+        }
+
+        try {
+            tl.debug("Code Coverage data will be appeneded to build file: " + this.buildFile);
+            util.appendTextToFileSync(this.buildFile, codeCoveragePluginData);
+            tl.debug("Appended code coverage data");
+        } catch (error) {
+            tl.warning(tl.loc("FailedToAppendCC", error));
+            return Q.reject<boolean>(tl.loc("FailedToAppendCC", error));
+        }
+        return Q.resolve<boolean>(true);
+    }
+
+    protected applyFilterPattern(filter: string): string[] {
+        let ccfilter = [];
+
+        if (!util.isNullOrWhitespace(filter)) {
+            str(util.trimToEmptyString(filter)).replaceAll(".", "/").s.split(":").forEach(exFilter => {
+                if (exFilter) {
+                    ccfilter.push(str(exFilter).endsWith("*") ? ("'" + exFilter + "/**'") : ("'" + exFilter + ".class'"));
+                }
+            });
+        }
+
+        tl.debug("Applying the filter pattern: " + filter + " op: " + ccfilter);
+        return ccfilter;
+    }
+}
diff --git a/Tasks/Common/codecoverage-tools/jacoco/jacoco.maven.ccenabler.ts b/Tasks/Common/codecoverage-tools/jacoco/jacoco.maven.ccenabler.ts
new file mode 100644
index 000000000000..7fc10c8ecee3
--- /dev/null
+++ b/Tasks/Common/codecoverage-tools/jacoco/jacoco.maven.ccenabler.ts
@@ -0,0 +1,172 @@
+/// <reference path="../../../../definitions/Q.d.ts" />
+/// <reference path="../../../../definitions/string.d.ts" />
+/// <reference path="../../../../definitions/vsts-task-lib.d.ts" />
+/// <reference path="../../../../definitions/node.d.ts" />
+
+import * as util from "../utilities";
+import * as tl from "vsts-task-lib/task";
+import * as ccc from "../codecoverageconstants";
+import * as cc from "../codecoverageenabler";
+import * as str from "string";
+import * as Q from "q";
+
+export class JacocoMavenCodeCoverageEnabler extends cc.JacocoCodeCoverageEnabler {
+
+    excludeFilter: string[];
+    includeFilter: string[];
+    reportDir: string;
+    sourceDirs: string;
+    classDirs: string;
+    reportBuildFile: string;
+
+    // -----------------------------------------------------
+    // Enable code coverage for Jacoco Maven Builds
+    // - enableCodeCoverage: CodeCoverageProperties  - ccProps
+    // -----------------------------------------------------    
+    public enableCodeCoverage(ccProps: { [name: string]: string }): Q.Promise<boolean> {
+        let _this = this;
+
+        tl.debug("Input parameters: " + JSON.stringify(ccProps));
+
+        _this.buildFile = ccProps["buildfile"];
+        _this.reportDir = ccProps["reportdirectory"];
+        _this.sourceDirs = ccProps["sourcedirectories"];
+        _this.classDirs = ccProps["classfilesdirectories"];
+        _this.reportBuildFile = ccProps["reportbuildfile"];
+
+        let classFilter = ccProps["classfilter"];
+        let filter = _this.extractFilters(classFilter);
+        _this.excludeFilter = _this.applyFilterPattern(filter.excludeFilter);
+        _this.includeFilter = _this.applyFilterPattern(filter.includeFilter);
+
+        return util.readXmlFileAsJson(_this.buildFile)
+            .then(function (resp) {
+                return _this.addCodeCoverageData(resp);
+            })
+            .thenResolve(true);
+    }
+
+    protected applyFilterPattern(filter: string): string[] {
+        let ccfilter = [];
+
+        if (!util.isNullOrWhitespace(filter)) {
+            str(util.trimToEmptyString(filter)).replaceAll(".", "/").s.split(":").forEach(exFilter => {
+                if (exFilter) {
+                    ccfilter.push(str(exFilter).endsWith("*") ? ("**/" + exFilter + "/**") : ("**/" + exFilter + ".class"));
+                }
+            });
+        }
+
+        tl.debug("Applying the filter pattern: " + filter + " op: " + ccfilter);
+        return ccfilter;
+    }
+
+    protected addCodeCoverageData(pomJson: any): Q.Promise<any[]> {
+        let _this = this;
+
+        if (!pomJson.project) {
+            Q.reject(tl.loc("InvalidBuildFile"));
+        }
+
+        let isMultiModule = false;
+        if (pomJson.project.modules) {
+            tl.debug("Multimodule project detected");
+            isMultiModule = true;
+        }
+
+        let promises = [_this.addCodeCoveragePluginData(pomJson)];
+        if (isMultiModule) {
+            promises.push(_this.createMultiModuleReport(_this.reportDir));
+        }
+
+        return Q.all(promises);
+    }
+
+    protected addCodeCoverageNodes(buildJsonContent: any): Q.Promise<any> {
+        let _this = this;
+
+        if (!buildJsonContent.project.build) {
+            tl.debug("Build tag is not present");
+            buildJsonContent.project.build = {};
+        }
+
+        let buildNode = _this.getBuildDataNode(buildJsonContent);
+        let pluginsNode = _this.getPluginDataNode(buildNode);
+        let ccContent = ccc.jacocoMavenPluginEnable(_this.includeFilter, _this.excludeFilter, _this.reportDir);
+        util.addPropToJson(pluginsNode, "plugin", ccContent);
+        return Q.resolve(buildJsonContent);
+    }
+
+    private getBuildDataNode(buildJsonContent: any): any {
+        let buildNode = null;
+        if (!buildJsonContent.project.build || typeof buildJsonContent.project.build === "string") {
+            buildNode = {};
+            buildJsonContent.project.build = buildNode;
+        }
+
+        if (buildJsonContent.project.build instanceof Array) {
+            if (typeof buildJsonContent.project.build[0] === "string") {
+                buildNode = {};
+                buildJsonContent.project.build[0] = buildNode;
+            } else {
+                buildNode = buildJsonContent.project.build[0];
+            }
+        }
+        return buildNode;
+    }
+
+    private getPluginDataNode(buildNode: any): any {
+        let pluginsNode = {};
+
+        if (buildNode.pluginManagement) {
+            if (typeof buildNode.pluginManagement === "string") {
+                buildNode.pluginManagement = {};
+            }
+            if (buildNode.pluginManagement instanceof Array) {
+                pluginsNode = buildNode.pluginManagement[0].plugins;
+            } else {
+                pluginsNode = buildNode.pluginManagement.plugins;
+            }
+        } else {
+            if (!buildNode.plugins || typeof buildNode.plugins === "string") {
+                buildNode.plugins = {};
+            }
+            if (buildNode.plugins instanceof Array) {
+                if (typeof buildNode.plugins[0] === "string") {
+                    pluginsNode = {};
+                    buildNode.plugins[0] = pluginsNode;
+                } else {
+                    pluginsNode = buildNode.plugins[0];
+                }
+            } else {
+                pluginsNode = buildNode.plugins;
+            }
+        }
+        return pluginsNode;
+    }
+
+    protected createMultiModuleReport(reportDir: string): Q.Promise<any> {
+        let _this = this;
+        let srcDirs = _this.sourceDirs;
+        let classDirs = _this.classDirs;
+        let includeFilter = _this.includeFilter.join(",");
+        let excludeFilter = _this.excludeFilter.join(",");
+
+        if (str(srcDirs).isEmpty()) {
+            srcDirs = ".";
+        }
+        if (str(classDirs).isEmpty()) {
+            classDirs = ".";
+        }
+
+        return util.writeFile(_this.reportBuildFile, ccc.jacocoMavenMultiModuleReport(reportDir, srcDirs, classDirs, includeFilter, excludeFilter));
+    }
+
+    protected addCodeCoveragePluginData(pomJson: any): Q.Promise<any> {
+        let _this = this;
+        return _this.addCodeCoverageNodes(pomJson)
+            .then(function (content) {
+                return util.writeJsonAsXmlFile(_this.buildFile, content);
+            });
+    }
+}
diff --git a/Tasks/Common/codecoverage-tools/module.json b/Tasks/Common/codecoverage-tools/module.json
new file mode 100644
index 000000000000..12d27d8ded36
--- /dev/null
+++ b/Tasks/Common/codecoverage-tools/module.json
@@ -0,0 +1,7 @@
+{
+    "messages": {
+        "InvalidBuildFile": "Invalid or unsupported build file",
+        "FileNotFound": "File or folder doesn't exist: %s",
+        "FailedToAppendCC": "Unable to append code coverage data: %s"
+    }
+}
\ No newline at end of file
diff --git a/Tasks/Common/codecoverage-tools/package.json b/Tasks/Common/codecoverage-tools/package.json
new file mode 100644
index 000000000000..51659b926041
--- /dev/null
+++ b/Tasks/Common/codecoverage-tools/package.json
@@ -0,0 +1,17 @@
+{
+    "name": "codecoverage-tools",
+    "version": "1.0.0",
+    "author": "Microsoft Corporation",
+    "description": "Build with Gradle",
+    "license": "MIT",
+    "bugs": {
+        "url": "https://github.com/Microsoft/vso-agent-tasks/issues"
+    },
+    "dependencies": {
+        "xml2js": "^0.4.17",
+        "fs-extra": "^0.30.0",
+        "os": "^0.1.1",
+        "string": "^3.3.1",
+        "vsts-task-lib": "0.9.7"
+    }
+}
\ No newline at end of file
diff --git a/Tasks/Common/codecoverage-tools/utilities.d.ts b/Tasks/Common/codecoverage-tools/utilities.d.ts
new file mode 100644
index 000000000000..fe9f34f74f31
--- /dev/null
+++ b/Tasks/Common/codecoverage-tools/utilities.d.ts
@@ -0,0 +1,27 @@
+/// <reference path="../../../definitions/Q.d.ts" />
+/// <reference path="../../../definitions/string.d.ts" />
+/// <reference path="../../../definitions/xml2js.d.ts" />
+/// <reference path="../../../definitions/vsts-task-lib.d.ts" />
+/// <reference path="../../../definitions/node.d.ts" />
+import * as Q from "q";
+export interface GetOrCreateResult<T> {
+    created: boolean;
+    result: T;
+}
+export declare function sharedSubString(string1: string, string2: string): string;
+export declare function sortStringArray(list: any): string[];
+export declare function isDirectoryExists(path: string): boolean;
+export declare function isFileExists(path: string): boolean;
+export declare function isNullOrWhitespace(input: any): boolean;
+export declare function trimToEmptyString(input: any): any;
+export declare function appendTextToFileSync(filePath: string, fileContent: string): void;
+export declare function prependTextToFileSync(filePath: string, fileContent: string): void;
+export declare function insertTextToFileSync(filePath: string, prependFileContent?: string, appendFileContent?: string): void;
+export declare function trimEnd(data: string, trimChar: string): string;
+export declare function readXmlFileAsJson(filePath: string): Q.Promise<any>;
+export declare function readFile(filePath: string, encoding: string): Q.Promise<string>;
+export declare function convertXmlStringToJson(xmlContent: string): Q.Promise<any>;
+export declare function convertXmlStringToJsonSync(xmlContent: string): any;
+export declare function writeJsonAsXmlFile(filePath: string, jsonContent: any): Q.Promise<void>;
+export declare function writeFile(filePath: string, fileContent: string): Q.Promise<void>;
+export declare function addPropToJson(obj: any, propName: string, value: any): void;
diff --git a/Tasks/Common/codecoverage-tools/utilities.ts b/Tasks/Common/codecoverage-tools/utilities.ts
new file mode 100644
index 000000000000..638af90bbb5a
--- /dev/null
+++ b/Tasks/Common/codecoverage-tools/utilities.ts
@@ -0,0 +1,189 @@
+/// <reference path="../../../definitions/Q.d.ts" />
+/// <reference path="../../../definitions/string.d.ts" />
+/// <reference path="../../../definitions/xml2js.d.ts" />
+/// <reference path="../../../definitions/vsts-task-lib.d.ts" />
+/// <reference path="../../../definitions/node.d.ts" />
+
+import * as Q from "q";
+import * as fs from "fs";
+import * as tl from "vsts-task-lib/task";
+import * as path from "path";
+import * as str from "string";
+import * as xml2js from "xml2js";
+import * as fse from "fs-extra";
+
+export interface GetOrCreateResult<T> {
+    created: boolean;
+    result: T;
+}
+
+// returns a substring that is common from first. For example, for "abcd" and "abdf", "ab" is returned.
+export function sharedSubString(string1: string, string2: string): string {
+    let ret = "";
+    let index = 1;
+    while (string1.substring(0, index) === string2.substring(0, index)) {
+        ret = string1.substring(0, index);
+        index++;
+    }
+    return ret;
+}
+
+// sorts string array in ascending order
+export function sortStringArray(list): string[] {
+    let sortedFiles: string[] = list.sort((a, b) => {
+        if (a > b) {
+            return 1;
+        } else if (a < b) {
+            return -1;
+        }
+        return 0;
+    });
+    return sortedFiles;
+}
+
+// returns true if path exists and it is a directory else false.
+export function isDirectoryExists(path: string): boolean {
+    try {
+        return tl.stats(path).isDirectory();
+    } catch (error) {
+        return false;
+    }
+}
+
+// returns true if path exists and it is a file else false.
+export function isFileExists(path: string): boolean {
+    try {
+        return tl.stats(path).isFile();
+    } catch (error) {
+        return false;
+    }
+}
+
+// returns true if given string is null or whitespace.
+export function isNullOrWhitespace(input) {
+    if (typeof input === "undefined" || input == null) {
+        return true;
+    }
+    return input.replace(/\s/g, "").length < 1;
+}
+
+// returns empty string if the given value is undefined or null.
+export function trimToEmptyString(input) {
+    if (typeof input === "undefined" || input == null) {
+        return "";
+    }
+    return input.trim();
+}
+
+// appends given text to file.
+export function appendTextToFileSync(filePath: string, fileContent: string) {
+    if (isFileExists(filePath)) {
+        fs.appendFileSync(filePath, fileContent);
+    } else {
+        throw new Error(tl.loc("FileNotFound", filePath));
+    }
+}
+
+// prepends given text to start of file.
+export function prependTextToFileSync(filePath: string, fileContent: string) {
+    if (isFileExists(filePath)) {
+        let data = fs.readFileSync(filePath); // read existing contents into data
+        let fd = fs.openSync(filePath, "w+");
+        let buffer = new Buffer(fileContent);
+        fs.writeSync(fd, buffer, 0, buffer.length, 0); // write new data
+        fs.writeSync(fd, data, 0, data.length, 0); // append old data
+        fs.close(fd);
+    }
+}
+
+// single utility for appending text and prepending text to file.
+export function insertTextToFileSync(filePath: string, prependFileContent?: string, appendFileContent?: string) {
+    if (isFileExists(filePath) && (prependFileContent || appendFileContent)) {
+        let existingData = fs.readFileSync(filePath); // read existing contents into data
+        let fd = fs.openSync(filePath, "w+");
+        let preTextLength = prependFileContent ? prependFileContent.length : 0;
+
+        if (prependFileContent) {
+            let prependBuffer = new Buffer(prependFileContent);
+            fs.writeSync(fd, prependBuffer, 0, prependBuffer.length, 0); // write new data
+        }
+        fs.writeSync(fd, existingData, 0, existingData.length, preTextLength); // append old data
+        if (appendFileContent) {
+            let appendBuffer = new Buffer(appendFileContent);
+            fs.writeSync(fd, appendBuffer, 0, appendBuffer.length, existingData.length + preTextLength);
+        }
+        fs.close(fd);
+    }
+}
+
+// trim the given character if it exists in the end of string.
+export function trimEnd(data: string, trimChar: string) {
+    if (!trimChar || !data) {
+        return data;
+    }
+
+    if (str(data).endsWith(trimChar)) {
+        return data.substring(0, data.length - trimChar.length);
+    } else {
+        return data;
+    }
+}
+
+export function readXmlFileAsJson(filePath: string): Q.Promise<any> {
+    tl.debug("Reading XML file: " + filePath);
+    return readFile(filePath, "utf-8")
+        .then(convertXmlStringToJson);
+}
+
+export function readFile(filePath: string, encoding: string): Q.Promise<string> {
+    return Q.nfcall<string>(fs.readFile, filePath, encoding);
+}
+
+export function convertXmlStringToJson(xmlContent: string): Q.Promise<any> {
+    tl.debug("Converting XML file to JSON");
+    return Q.nfcall<any>(xml2js.parseString, xmlContent);
+}
+
+export function writeJsonAsXmlFile(filePath: string, jsonContent: any): Q.Promise<void> {
+    let builder = new xml2js.Builder();
+    tl.debug("Writing JSON as XML file: " + filePath);
+    let xml = builder.buildObject(jsonContent);
+    xml = str(xml).replaceAll("&#xD;", "").s;
+    return writeFile(filePath, xml);
+}
+
+export function writeFile(filePath: string, fileContent: string): Q.Promise<void> {
+    tl.debug("Creating dir if not exists: " + path.dirname(filePath));
+    fse.mkdirpSync(path.dirname(filePath));
+    tl.debug("Check dir: " + fs.existsSync(path.dirname(filePath)));
+    return Q.nfcall<void>(fs.writeFile, filePath, fileContent);
+}
+
+export function addPropToJson(obj: any, propName: string, value: any): void {
+    tl.debug("Adding property to JSON: " + propName);
+    if (obj === "undefined") {
+        obj = {};
+    }
+
+    if (obj instanceof Array) {
+        let propNode = obj.find(o => o[propName]);
+        if (propNode) {
+            obj = propNode;
+        }
+    }
+
+    if (propName in obj) {
+        if (obj[propName] instanceof Array) {
+            obj[propName].push(value);
+        } else if (typeof obj[propName] !== "object") {
+            obj[propName] = [obj[propName], value];
+        }
+    } else if (obj instanceof Array) {
+        let prop = {};
+        prop[propName] = value;
+        obj.push(prop);
+    } else {
+        obj[propName] = value;
+    }
+}
+
diff --git a/Tasks/Gradle/gradletask.ts b/Tasks/Gradle/gradletask.ts
index b1e952021ce1..dea742619af9 100644
--- a/Tasks/Gradle/gradletask.ts
+++ b/Tasks/Gradle/gradletask.ts
@@ -1,25 +1,24 @@
 /// <reference path="../../definitions/vsts-task-lib.d.ts" />
+/// <reference path="../../definitions/codecoveragefactory.d.ts" />
 
 import tl = require('vsts-task-lib/task');
 import fs = require('fs');
 import path = require('path');
+import * as Q from "q";
+import os = require('os');
 
-// Lowercased file names are to lessen the likelihood of xplat issues
 import sqCommon = require('./CodeAnalysis/SonarQube/common');
 import sqGradle = require('./CodeAnalysis/gradlesonar');
-
 import {CodeAnalysisOrchestrator} from './CodeAnalysis/Common/CodeAnalysisOrchestrator';
 import {BuildOutput, BuildEngine} from './CodeAnalysis/Common/BuildOutput';
 import {PmdTool} from './CodeAnalysis/Common/PmdTool';
 import {CheckstyleTool} from './CodeAnalysis/Common/CheckstyleTool';
-
-import os = require('os');
+import {CodeCoverageEnablerFactory} from 'codecoverage-tools/codecoveragefactory';
 
 var isWindows = os.type().match(/^Win/);
 
 // Set up localization resource file
 tl.setResourcePath(path.join(__dirname, 'task.json'));
-
 var wrapperScript = tl.getPathInput('wrapperScript', true, true);
 
 if (isWindows) {
@@ -43,7 +42,7 @@ if (!cwd) {
 }
 tl.cd(cwd);
 
-var gb = tl.createToolRunner(wrapperScript);
+var gb = tl.tool(wrapperScript);
 var javaHomeSelection = tl.getInput('javaHomeSelection', true);
 var specifiedJavaHome = null;
 var ccTool = tl.getInput('codeCoverageTool');
@@ -54,6 +53,7 @@ var summaryFile: string = null;
 var reportDirectory: string = null;
 var inputTasks: string[] = tl.getDelimitedInput('tasks', ' ', true);
 var isSonarQubeEnabled: boolean = sqCommon.isSonarQubeAnalysisEnabled();
+let reportingTaskName = "";
 
 let buildOutput: BuildOutput = new BuildOutput(tl.getVariable('build.sourcesDirectory'), BuildEngine.Gradle);
 var codeAnalysisOrchestrator = new CodeAnalysisOrchestrator(
@@ -64,7 +64,7 @@ if (isCodeCoverageOpted && inputTasks.indexOf('clean') == -1) {
     gb.arg('clean'); //if user opts for code coverage, we append clean functionality to make sure any uninstrumented class files are removed
 }
 
-gb.argString(tl.getInput('options', false));
+gb.arg(tl.getInput('options', false));
 gb.arg(inputTasks);
 
 // update JAVA_HOME if user selected specific JDK version or set path manually
@@ -94,43 +94,44 @@ if (specifiedJavaHome) {
     tl.debug('Set JAVA_HOME to ' + specifiedJavaHome);
     process.env['JAVA_HOME'] = specifiedJavaHome;
 }
-
-if (isCodeCoverageOpted) {
-    tl.debug("Option to enable code coverage was selected and is being applied.");
-    enableCodeCoverage();
+ 
+/* Actual execution of Build and further flows*/
+async function execBuild() {
+    await execEnableCodeCoverage();
+    if (reportingTaskName && reportingTaskName != "") {
+        gb.arg(reportingTaskName);
+    }
+    
+    enableSonarQubeAnalysis();
+    var gradleResult;
+    gb.exec()
+        .then(function (code) {
+            gradleResult = code;
+            publishTestResults(publishJUnitResults, testResultsFiles);
+            publishCodeCoverage(isCodeCoverageOpted);
+            return processCodeAnalysisResults();
+        })
+        .then(() => {
+            tl.exit(gradleResult);
+        })
+        .fail(function (err) {
+            console.error(err);
+            tl.debug('taskRunner fail');
+            tl.exit(1);
+        });
 }
 
-if (isSonarQubeEnabled) {
-    // Looks like: 'SonarQube analysis is enabled.'
-    console.log(tl.loc('codeAnalysis_ToolIsEnabled'), sqCommon.toolName);
+function enableSonarQubeAnalysis() {
+    if (isSonarQubeEnabled) {
+        // Looks like: 'SonarQube analysis is enabled.'
+        console.log(tl.loc('codeAnalysis_ToolIsEnabled'), sqCommon.toolName);
 
-    gb = sqGradle.applyEnabledSonarQubeArguments(gb);
-    gb = sqGradle.applySonarQubeCodeCoverageArguments(gb, isCodeCoverageOpted, ccTool, summaryFile);
+        gb = sqGradle.applyEnabledSonarQubeArguments(gb);
+        gb = sqGradle.applySonarQubeCodeCoverageArguments(gb, isCodeCoverageOpted, ccTool, summaryFile);
+    }
+    gb = codeAnalysisOrchestrator.configureBuild(gb);
 }
 
-gb = codeAnalysisOrchestrator.configureBuild(gb);
-
-setGradleOpts();
-
-var gradleResult;
-gb.exec()
-    .then(function (code) {
-        gradleResult = code;
-
-        publishTestResults(publishJUnitResults, testResultsFiles);
-        publishCodeCoverage(isCodeCoverageOpted);
-        return processCodeAnalysisResults();
-    })
-    .then(() => {
-        tl.exit(gradleResult);
-    })
-    .fail(function (err) {
-        publishTestResults(publishJUnitResults, testResultsFiles);
-        console.error(err);
-        tl.debug('taskRunner fail');
-        tl.exit(1);
-    });
-
 function processCodeAnalysisResults(): Q.Promise<void> {
 
     tl.debug('Processing code analysis results');
@@ -174,7 +175,21 @@ function publishTestResults(publishJUnitResults, testResultsFiles: string) {
     }
 }
 
-function enableCodeCoverage() {
+function execEnableCodeCoverage(): Q.Promise<void> {
+    return enableCodeCoverage()
+        .then(function (resp) {
+            tl.debug("Enabled code coverage successfully");
+        }).catch(function (err) {
+            tl.warning("Failed to enable code coverage: " + err);
+        });
+};
+
+function enableCodeCoverage(): Q.Promise<any> {
+    if (!isCodeCoverageOpted) {
+        return Q.resolve(true);
+    }
+
+    tl.debug("Option to enable code coverage was selected and is being applied.");
     var classFilter: string = tl.getInput('classFilter');
     var classFilesDirectories: string = tl.getInput('classFilesDirectories');
     var buildRootPath = cwd;
@@ -186,15 +201,15 @@ function enableCodeCoverage() {
         var summaryFileName = "summary.xml";
 
         if (isMultiModule) {
-            var reportingTaskName = "jacocoRootReport";
+            reportingTaskName = "jacocoRootReport";
         }
         else {
-            var reportingTaskName = "jacocoTestReport";
+            reportingTaskName = "jacocoTestReport";
         }
     }
     else if (ccTool.toLowerCase() == "cobertura") {
         var summaryFileName = "coverage.xml";
-        var reportingTaskName = "cobertura";
+        reportingTaskName = "cobertura";
     }
 
     summaryFile = path.join(reportDirectory, summaryFileName);
@@ -209,21 +224,14 @@ function enableCodeCoverage() {
     buildProps['reportdirectory'] = reportDirectoryName;
     buildProps['ismultimodule'] = String(isMultiModule);
 
-    try {
-        var codeCoverageEnabler = new tl.CodeCoverageEnabler('Gradle', ccTool);
-        codeCoverageEnabler.enableCodeCoverage(buildProps);
-        tl.debug("Code coverage is successfully enabled.");
-    }
-    catch (Error) {
-        tl.warning("Enabling code coverage failed. Check the build logs for errors.");
-    }
-    gb.arg(reportingTaskName);
+    let ccEnabler = new CodeCoverageEnablerFactory().getTool("gradle", ccTool.toLowerCase());
+    return ccEnabler.enableCodeCoverage(buildProps);
 }
 
 function isMultiModuleProject(wrapperScript: string): boolean {
-    var gradleBuild = tl.createToolRunner(wrapperScript);
+    var gradleBuild = tl.tool(wrapperScript);
     gradleBuild.arg("properties");
-    gradleBuild.argString(tl.getInput('options', false));
+    gradleBuild.arg(tl.getInput('options', false));
 
     var data = gradleBuild.execSync().stdout;
     if (typeof data != "undefined" && data) {
@@ -254,3 +262,6 @@ function publishCodeCoverage(isCodeCoverageOpted: boolean) {
         }
     }
 }
+
+setGradleOpts();
+execBuild();
\ No newline at end of file
diff --git a/Tasks/Gradle/package.json b/Tasks/Gradle/package.json
index ec0b778db6e4..968773cf6e36 100644
--- a/Tasks/Gradle/package.json
+++ b/Tasks/Gradle/package.json
@@ -9,6 +9,7 @@
   },
   "dependencies": {
     "xml2js": "^0.4.16",
+    "vsts-task-lib": "0.9.7",
     "request": "^2.74.0"
   }
 }
\ No newline at end of file
diff --git a/Tasks/Gradle/task.json b/Tasks/Gradle/task.json
index 67bce37154f7..64d59b03cd06 100644
--- a/Tasks/Gradle/task.json
+++ b/Tasks/Gradle/task.json
@@ -12,7 +12,7 @@
     "version": {
         "Major": 1,
         "Minor": 0,
-        "Patch": 56
+        "Patch": 57
     },
     "demands": [
         "java"
diff --git a/Tasks/Gradle/task.loc.json b/Tasks/Gradle/task.loc.json
index 8301e2e85cb1..b2ed81bfe9c1 100644
--- a/Tasks/Gradle/task.loc.json
+++ b/Tasks/Gradle/task.loc.json
@@ -12,7 +12,7 @@
   "version": {
     "Major": 1,
     "Minor": 0,
-    "Patch": 56
+    "Patch": 57
   },
   "demands": [
     "java"
diff --git a/Tasks/Maven/maventask.ts b/Tasks/Maven/maventask.ts
index e138d7113579..2685b7ebeb6c 100644
--- a/Tasks/Maven/maventask.ts
+++ b/Tasks/Maven/maventask.ts
@@ -1,4 +1,5 @@
 /// <reference path="../../definitions/vsts-task-lib.d.ts" />
+/// <reference path="../../definitions/codecoveragefactory.d.ts" />
 
 import Q = require('q');
 import os = require('os');
@@ -9,7 +10,7 @@ import tl = require('vsts-task-lib/task');
 import {ToolRunner} from 'vsts-task-lib/toolrunner';
 import sqCommon = require('./CodeAnalysis/SonarQube/common');
 import sqMaven = require('./CodeAnalysis/mavensonar');
-
+import {CodeCoverageEnablerFactory} from 'codecoverage-tools/codecoveragefactory';
 import {CodeAnalysisOrchestrator} from "./CodeAnalysis/Common/CodeAnalysisOrchestrator";
 import {BuildOutput, BuildEngine} from './CodeAnalysis/Common/BuildOutput';
 import {PmdTool} from './CodeAnalysis/Common/PmdTool';
@@ -27,6 +28,12 @@ var publishJUnitResults: string = tl.getInput('publishJUnitResults');
 var testResultsFiles: string = tl.getInput('testResultsFiles', true);
 var ccTool = tl.getInput('codeCoverageTool');
 var isCodeCoverageOpted = (typeof ccTool != "undefined" && ccTool && ccTool.toLowerCase() != 'none');
+var isSonarQubeEnabled:boolean = false;
+var summaryFile: string = null;
+var reportDirectory: string = null;
+var reportPOMFile: string = null;
+var execFileJacoco: string = null;
+var ccReportTask: string = null;
 
 let buildOutput: BuildOutput = new BuildOutput(tl.getVariable('build.sourcesDirectory'), BuildEngine.Maven);
 var codeAnalysisOrchestrator:CodeAnalysisOrchestrator = new CodeAnalysisOrchestrator(
@@ -111,109 +118,100 @@ if (specifiedJavaHome) {
     tl.setVariable('JAVA_HOME', specifiedJavaHome);
 }
 
-if (isCodeCoverageOpted) {
-    var summaryFile: string = null;
-    var reportDirectory: string = null;
-    var reportPOMFile: string = null;
-    var execFileJacoco: string = null;
-    var ccReportTask: string = null;
-    enableCodeCoverage();
-}
-else {
-    tl.debug("Option to enable code coverage was not selected and is being skipped.");
-}
-
-// Maven task orchestration occurs as follows:
-// 1. Check that Maven exists by executing it to retrieve its version.
-// 2. Apply any goals for static code analysis tools selected by the user.
-// 3. Run Maven. Compilation or test errors will cause this to fail.
-//    In case the build has failed, the analysis will still succeed but the report will have less data. 
-// 4. Attempt to collate and upload static code analysis build summaries and artifacts.
-// 5. Always publish test results even if tests fail, causing this task to fail.
-// 6. If #3 or #4 above failed, exit with an error code to mark the entire step as failed.
-
-var userRunFailed: boolean = false;
-var codeAnalysisFailed: boolean = false;
-
-// Setup tool runner that executes Maven only to retrieve its version
-var mvnGetVersion = tl.createToolRunner(mvnExec);
-mvnGetVersion.arg('-version');
-
-configureMavenOpts();
-
-// 1. Check that Maven exists by executing it to retrieve its version.
-mvnGetVersion.exec()
-    .fail(function (err) {
-        console.error("Maven is not installed on the agent");
-        tl.exit(1);  // tl.exit sets the step result but does not stop execution
-        process.exit(1);
-    })
-    .then(function (code) {
-        // Setup tool runner to execute Maven goals
-        var mvnRun = tl.createToolRunner(mvnExec);
-        mvnRun.arg('-f');
-        mvnRun.pathArg(mavenPOMFile);
-        mvnRun.argString(mavenOptions);
-        if (isCodeCoverageOpted && mavenGoals.indexOf('clean') == -1) {
-            mvnRun.arg('clean');
-        }
-        mvnRun.arg(mavenGoals);
+async function execBuild() {
+    // Maven task orchestration occurs as follows:
+    // 1. Check that Maven exists by executing it to retrieve its version.
+    // 2. Apply any goals for static code analysis tools selected by the user.
+    // 3. Run Maven. Compilation or test errors will cause this to fail.
+    //    In case the build has failed, the analysis will still succeed but the report will have less data. 
+    // 4. Attempt to collate and upload static code analysis build summaries and artifacts.
+    // 5. Always publish test results even if tests fail, causing this task to fail.
+    // 6. If #3 or #4 above failed, exit with an error code to mark the entire step as failed.
+
+    ccReportTask = await execEnableCodeCoverage();
+    var userRunFailed: boolean = false;
+    var codeAnalysisFailed: boolean = false;
+
+    // Setup tool runner that executes Maven only to retrieve its version
+    var mvnGetVersion = tl.tool(mvnExec);
+    mvnGetVersion.arg('-version');
+
+    configureMavenOpts();
+
+    // 1. Check that Maven exists by executing it to retrieve its version.
+    mvnGetVersion.exec()
+        .fail(function (err) {
+            console.error("Maven is not installed on the agent");
+            tl.exit(1);  // tl.exit sets the step result but does not stop execution
+            process.exit(1);
+        })
+        .then(function (code) {
+            // Setup tool runner to execute Maven goals
+            var mvnRun = tl.tool(mvnExec);
+            mvnRun.arg('-f');
+            mvnRun.arg(mavenPOMFile);
+            mvnRun.arg(mavenOptions);
+            if (isCodeCoverageOpted && mavenGoals.indexOf('clean') == -1) {
+                mvnRun.arg('clean');
+            }
+            mvnRun.arg(mavenGoals);
 
-        // 2. Apply any goals for static code analysis tools selected by the user.
-        mvnRun = sqMaven.applySonarQubeArgs(mvnRun, execFileJacoco);
-        mvnRun = codeAnalysisOrchestrator.configureBuild(mvnRun);
+            // 2. Apply any goals for static code analysis tools selected by the user.
+            mvnRun = sqMaven.applySonarQubeArgs(mvnRun, execFileJacoco);
+             mvnRun = codeAnalysisOrchestrator.configureBuild(mvnRun);
 
-        // Read Maven standard output
-        mvnRun.on('stdout', function (data) {
-            processMavenOutput(data);
-        });
+            // Read Maven standard output
+            mvnRun.on('stdout', function (data) {
+                processMavenOutput(data);
+            });
 
-        // 3. Run Maven. Compilation or test errors will cause this to fail.
-        return mvnRun.exec(); // Run Maven with the user specified goals
-    })
-    .fail(function (err) {
-        console.error(err.message);
-        userRunFailed = true; // Record the error and continue
-    })
-    .then(function (code) {
-        // 4. Attempt to collate and upload static code analysis build summaries and artifacts.
-
-        // The files won't be created if the build failed, and the user should probably fix their build first.
-        if (userRunFailed) {
-            console.error('Could not retrieve code analysis results - Maven run failed.');
-            return;
-        }
+            // 3. Run Maven. Compilation or test errors will cause this to fail.
+            return mvnRun.exec(); // Run Maven with the user specified goals
+        })
+        .fail(function (err) {
+            console.error(err.message);
+            userRunFailed = true; // Record the error and continue
+        })
+        .then(function (code) {
+            // 4. Attempt to collate and upload static code analysis build summaries and artifacts.
+
+            // The files won't be created if the build failed, and the user should probably fix their build first.
+            if (userRunFailed) {
+                console.error('Could not retrieve code analysis results - Maven run failed.');
+                return;
+            }
 
-        // Otherwise, start uploading relevant build summaries.
-        tl.debug('Processing code analysis results');
-        return sqMaven.processSonarQubeIntegration()
-            .then(() => {
-                return codeAnalysisOrchestrator.publishCodeAnalysisResults();
-            });
-    })
-    .fail(function (err) {
-        console.error(err.message);
-        // Looks like: "Code analysis failed."
-        console.error(tl.loc('codeAnalysis_ToolFailed', 'Code'));
-        codeAnalysisFailed = true;
-    })
-    .then(function () {
-        // 5. Always publish test results even if tests fail, causing this task to fail.
-        if (publishJUnitResults == 'true') {
-            publishJUnitTestResults(testResultsFiles);
-        }
-        publishCodeCoverage(isCodeCoverageOpted);
+            // Otherwise, start uploading relevant build summaries.
+            tl.debug('Processing code analysis results');
+            return sqMaven.processSonarQubeIntegration()
+                .then(() => {
+                    return codeAnalysisOrchestrator.publishCodeAnalysisResults();
+                });
+        })
+        .fail(function (err) {
+            console.error(err.message);
+            // Looks like: "Code analysis failed."
+            console.error(tl.loc('codeAnalysis_ToolFailed', 'Code'));
+            codeAnalysisFailed = true;
+        })
+        .then(function () {
+            // 5. Always publish test results even if tests fail, causing this task to fail.
+            if (publishJUnitResults == 'true') {
+                publishJUnitTestResults(testResultsFiles);
+            }
+            publishCodeCoverage(isCodeCoverageOpted);
 
-        // 6. If #3 or #4 above failed, exit with an error code to mark the entire step as failed.
-        if (userRunFailed || codeAnalysisFailed) {
-            tl.exit(1); // Set task failure
-        }
-        else {
-            tl.exit(0); // Set task success
-        }
+            // 6. If #3 or #4 above failed, exit with an error code to mark the entire step as failed.
+            if (userRunFailed || codeAnalysisFailed) {
+                tl.exit(1); // Set task failure
+            }
+            else {
+                tl.exit(0); // Set task success
+            }
 
-        // Do not force an exit as publishing results is async and it won't have finished 
-    });
+            // Do not force an exit as publishing results is async and it won't have finished 
+        });
+}
 
 // Configure the JVM associated with this run.
 function configureMavenOpts() {
@@ -253,7 +251,22 @@ function publishJUnitTestResults(testResultsFiles: string) {
     tp.publish(matchingJUnitResultFiles, true, "", "", "", true);
 }
 
-function enableCodeCoverage() {
+function execEnableCodeCoverage(): Q.Promise<string> {
+    return enableCodeCoverage()
+        .then(function (resp) {
+            tl.debug("Enabled code coverage successfully");
+            return "CodeCoverage_9064e1d0";
+        }).catch(function (err) {
+            tl.warning("Failed to enable code coverage: " + err);
+            return "";
+        });
+};
+
+function enableCodeCoverage() : Q.Promise<any> {
+    if(!isCodeCoverageOpted){
+        return Q.resolve(true);
+    }
+
     var classFilter: string = tl.getInput('classFilter');
     var classFilesDirectories: string = tl.getInput('classFilesDirectories');
     var sourceDirectories: string = tl.getInput('srcDirectories');
@@ -262,7 +275,6 @@ function enableCodeCoverage() {
     var reportPOMFileName = "CCReportPomA4D283EG.xml";
     reportPOMFile = path.join(buildRootPath, reportPOMFileName);
     var targetDirectory = path.join(buildRootPath, "target");
-    ccReportTask = "jacoco:report";
 
     if (ccTool.toLowerCase() == "jacoco") {
         var reportDirectoryName = "CCReport43F6D5EF";
@@ -295,31 +307,25 @@ function enableCodeCoverage() {
     buildProps['reportdirectory'] = reportDirectory;
     buildProps['reportbuildfile'] = reportPOMFile;
 
-    try {
-        var codeCoverageEnabler = new tl.CodeCoverageEnabler('Maven', ccTool);
-        codeCoverageEnabler.enableCodeCoverage(buildProps);
-        tl.debug("Code coverage is successfully enabled.");
-    }
-    catch (Error) {
-        tl.warning("Enabling code coverage failed. Check the build logs for errors.");
-    }
+    let ccEnabler = new CodeCoverageEnablerFactory().getTool("maven", ccTool.toLowerCase());
+    return ccEnabler.enableCodeCoverage(buildProps);
 }
 
 function publishCodeCoverage(isCodeCoverageOpted: boolean) {
-    if (isCodeCoverageOpted) {
+    if (isCodeCoverageOpted && ccReportTask) {
         tl.debug("Collecting code coverage reports");
 
         if (ccTool.toLowerCase() == "jacoco") {
-            var mvnReport = tl.createToolRunner(mvnExec);
+            var mvnReport = tl.tool(mvnExec);
             mvnReport.arg('-f');
             if (tl.exist(reportPOMFile)) {
                 // multi module project
-                mvnReport.pathArg(reportPOMFile);
+                mvnReport.arg(reportPOMFile);
                 mvnReport.arg("verify");
             }
             else {
-                mvnReport.pathArg(mavenPOMFile);
-                mvnReport.arg(ccReportTask);
+                mvnReport.arg(mavenPOMFile);
+                mvnReport.arg("verify");
             }
             mvnReport.exec().then(function (code) {
                 publishCCToTfs();
@@ -397,3 +403,5 @@ function processMavenOutput(data) {
         }
     }
 }
+
+execBuild();
diff --git a/Tasks/Maven/package.json b/Tasks/Maven/package.json
index 998cff10e139..d305e38081e0 100644
--- a/Tasks/Maven/package.json
+++ b/Tasks/Maven/package.json
@@ -9,6 +9,7 @@
   },
   "dependencies": {
     "xml2js": "^0.4.16",
+    "vsts-task-lib": "0.9.7",
     "request": "^2.74.0"
   }
 }
\ No newline at end of file
diff --git a/Tasks/Maven/task.json b/Tasks/Maven/task.json
index 2d3247e05909..847087945c01 100644
--- a/Tasks/Maven/task.json
+++ b/Tasks/Maven/task.json
@@ -16,7 +16,7 @@
     "version": {
         "Major": 1,
         "Minor": 0,
-        "Patch": 62
+        "Patch": 63
     },
     "minimumAgentVersion": "1.89.0",
     "instanceNameFormat": "Maven $(mavenPOMFile)",
diff --git a/Tasks/Maven/task.loc.json b/Tasks/Maven/task.loc.json
index ff422068f882..69c9af9d5792 100644
--- a/Tasks/Maven/task.loc.json
+++ b/Tasks/Maven/task.loc.json
@@ -16,7 +16,7 @@
   "version": {
     "Major": 1,
     "Minor": 0,
-    "Patch": 62
+    "Patch": 63
   },
   "minimumAgentVersion": "1.89.0",
   "instanceNameFormat": "ms-resource:loc.instanceNameFormat",
diff --git a/Tests/L0/ANT/_suite.ts b/Tests/L0/ANT/_suite.ts
index 442c0d15b31f..969a718ecbc6 100644
--- a/Tests/L0/ANT/_suite.ts
+++ b/Tests/L0/ANT/_suite.ts
@@ -174,7 +174,7 @@ describe('ANT Suite', function() {
             .then(() => {
                 // The response file will cause ANT to fail, but we are looking for the warning about ANT_HOME
                 assert(tr.ran('/usr/local/bin/ANT -version'), 'it should have run ANT -version');
-                assert(tr.invokedToolCount == 1, 'should have only run ANT 1 time');
+                assert(tr.invokedToolCount == 2, 'should have only run ANT 2 times');
                 assert(tr.resultWasSet, 'task should have set a result');
                 assert(tr.stderr.length > 0, 'should have written to stderr');
                 assert(tr.failed, 'task should have failed');
@@ -264,121 +264,6 @@ describe('ANT Suite', function() {
             });
     })
 
-    it('Ant fails when code coverage tool is Jacoco but no class files directory input is provided.', (done) => {
-        setResponseFile('antCodeCoverage.json');
-
-        var tr = new trm.TaskRunner('Ant');
-        tr.setInput('antBuildFile', '/build/build.xml'); // Make that checkPath returns true for this filename in the response file
-        tr.setInput('javaHomeSelection', 'JDKVersion');
-        tr.setInput('jdkVersion', 'default');
-        tr.setInput('testResultsFiles', '**/TEST-*.xml');
-        tr.setInput('codeCoverageTool', 'JaCoCo');
-
-        tr.run()
-            .then(() => {
-                assert(tr.resultWasSet, 'task should have set a result');
-                assert(tr.stderr.length > 0, 'should have written to stderr');
-                assert(tr.failed, 'task should have failed');
-                done();
-            })
-            .fail((err) => {
-                done(err);
-            });
-    })
-
-    it('Ant fails when code coverage tool is Cobertura but no class files directory input is provided.', (done) => {
-        setResponseFile('antCodeCoverage.json');
-
-        var tr = new trm.TaskRunner('Ant');
-        tr.setInput('antBuildFile', '/build/build.xml'); // Make that checkPath returns true for this filename in the response file
-        tr.setInput('javaHomeSelection', 'JDKVersion');
-        tr.setInput('jdkVersion', 'default');
-        tr.setInput('testResultsFiles', '**/TEST-*.xml');
-        tr.setInput('codeCoverageTool', 'Cobertura');
-
-        tr.run()
-            .then(() => {
-                assert(tr.resultWasSet, 'task should have set a result');
-                assert(tr.stderr.length > 0, 'should have written to stderr');
-                assert(tr.failed, 'task should have failed');
-                done();
-            })
-            .fail((err) => {
-                done(err);
-            });
-    })
-
-    it('Ant calls enable code coverage and publish code coverage when Cobertura is selected.', (done) => {
-        setResponseFile('antCodeCoverage.json');
-
-        var tr = new trm.TaskRunner('Ant');
-        tr.setInput('antBuildFile', '/build/build.xml'); // Make that checkPath returns true for this filename in the response file
-        tr.setInput('javaHomeSelection', 'JDKVersion');
-        tr.setInput('jdkVersion', 'default');
-        tr.setInput('testResultsFiles', '**/TEST-*.xml');
-        tr.setInput('codeCoverageTool', 'Cobertura');
-        tr.setInput('classFilesDirectories', 'class1');
-
-        tr.run()
-            .then(() => {
-                assert(tr.stdout.search(/##vso\[codecoverage.enable buildfile=\/build\/build.xml;classfilesdirectories=class1;summaryfile=coverage.xml;reportdirectory=\\build\\CCReport43F6D5EF;ccreporttask=CodeCoverage_9064e1d0;reportbuildfile=\\build\\CCReportBuildA4D283EG.xml;buildtool=Ant;codecoveragetool=Cobertura;\]/) >= 0 || tr.stdout.search(/##vso\[codecoverage.enable buildfile=\/build\/build.xml;classfilesdirectories=class1;summaryfile=coverage.xml;reportdirectory=\/build\/CCReport43F6D5EF;ccreporttask=CodeCoverage_9064e1d0;reportbuildfile=\/build\/CCReportBuildA4D283EG.xml;buildtool=Ant;codecoveragetool=Cobertura;\]/) >= 0, 'should have called enable code coverage.');
-                assert(tr.stdout.search(/##vso\[codecoverage.publish codecoveragetool=Cobertura;summaryfile=\\build\\CCReport43F6D5EF\\coverage.xml;reportdirectory=\\build\\CCReport43F6D5EF;\]/) >= 0 ||
-                    tr.stdout.search(/##vso\[codecoverage.publish codecoveragetool=Cobertura;summaryfile=\/build\/CCReport43F6D5EF\/coverage.xml;reportdirectory=\/build\/CCReport43F6D5EF;\]/) >= 0, 'should have called publish code coverage.');
-                done();
-            })
-            .fail((err) => {
-                assert.fail("task should not have failed");
-                done(err);
-            });
-    })
-
-    it('Ant calls enable code coverage and publish code coverage when Jacoco is selected.', (done) => {
-        setResponseFile('antCodeCoverage.json');
-
-        var tr = new trm.TaskRunner('Ant');
-        tr.setInput('antBuildFile', '/build/build.xml'); // Make that checkPath returns true for this filename in the response file
-        tr.setInput('javaHomeSelection', 'JDKVersion');
-        tr.setInput('jdkVersion', 'default');
-        tr.setInput('testResultsFiles', '**/TEST-*.xml');
-        tr.setInput('codeCoverageTool', 'JaCoCo');
-        tr.setInput('classFilesDirectories', 'class1');
-
-        tr.run()
-            .then(() => {
-                assert(tr.stdout.search(/##vso\[codecoverage.enable buildfile=\/build\/build.xml;classfilesdirectories=class1;summaryfile=coverage.xml;reportdirectory=\\build\\CCReport43F6D5EF;ccreporttask=CodeCoverage_9064e1d0;reportbuildfile=\\build\\CCReportBuildA4D283EG.xml;buildtool=Ant;codecoveragetool=JaCoCo;\]/) >= 0 || tr.stdout.search(/##vso\[codecoverage.enable buildfile=\/build\/build.xml;classfilesdirectories=class1;summaryfile=coverage.xml;reportdirectory=\/build\/CCReport43F6D5EF;ccreporttask=CodeCoverage_9064e1d0;reportbuildfile=\/build\/CCReportBuildA4D283EG.xml;buildtool=Ant;codecoveragetool=JaCoCo;\]/) >= 0, 'should have called enable code coverage.');
-                assert(tr.stdout.search(/##vso\[codecoverage.publish codecoveragetool=JaCoCo;summaryfile=\\build\\CCReport43F6D5EF\\coverage.xml;reportdirectory=\\build\\CCReport43F6D5EF;\]/) >= 0 ||
-                    tr.stdout.search(/##vso\[codecoverage.publish codecoveragetool=JaCoCo;summaryfile=\/build\/CCReport43F6D5EF\/coverage.xml;reportdirectory=\/build\/CCReport43F6D5EF;\]/) >= 0, 'should have called publish code coverage.');
-                done();
-            })
-            .fail((err) => {
-                assert.fail("task should not have failed");
-                done(err);
-            });
-    })
-
-    it('Ant calls enable code coverage but not publish code coverage when summary file is not generated.', (done) => {
-        setResponseFile('antGood.json');
-        // antGood.json doesnt mock the stat for summary file.
-        var tr = new trm.TaskRunner('Ant');
-        tr.setInput('antBuildFile', '/build/build.xml'); // Make that checkPath returns true for this filename in the response file
-        tr.setInput('javaHomeSelection', 'JDKVersion');
-        tr.setInput('jdkVersion', 'default');
-        tr.setInput('testResultsFiles', '**/TEST-*.xml');
-        tr.setInput('codeCoverageTool', 'JaCoCo');
-        tr.setInput('classFilesDirectories', 'class1');
-
-        tr.run()
-            .then(() => {
-                assert(tr.stdout.search(/##vso\[codecoverage.enable buildfile=\/build\/build.xml;classfilesdirectories=class1;summaryfile=coverage.xml;reportdirectory=\\build\\CCReport43F6D5EF;ccreporttask=CodeCoverage_9064e1d0;reportbuildfile=\\build\\CCReportBuildA4D283EG.xml;buildtool=Ant;codecoveragetool=JaCoCo;\]/) >= 0 || tr.stdout.search(/##vso\[codecoverage.enable buildfile=\/build\/build.xml;classfilesdirectories=class1;summaryfile=coverage.xml;reportdirectory=\/build\/CCReport43F6D5EF;ccreporttask=CodeCoverage_9064e1d0;reportbuildfile=\/build\/CCReportBuildA4D283EG.xml;buildtool=Ant;codecoveragetool=JaCoCo;\]/) >= 0, 'should have called enable code coverage.');
-                assert(tr.stdout.search(/##vso\[codecoverage.publish/) < 0, 'should have called publish code coverage.');
-                done();
-            })
-            .fail((err) => {
-                assert.fail("task should not have failed");
-                done(err);
-            });
-    })
-
     it('Ant build with Publish Test Results.', (done) => {
         setResponseFile('antGood.json');
 
diff --git a/Tests/L0/Common-CodeCoverageEnabler/_suite.ts b/Tests/L0/Common-CodeCoverageEnabler/_suite.ts
new file mode 100644
index 000000000000..69ee7967de42
--- /dev/null
+++ b/Tests/L0/Common-CodeCoverageEnabler/_suite.ts
@@ -0,0 +1,208 @@
+/// <reference path="../../../definitions/mocha.d.ts"/>
+/// <reference path="../../../definitions/node.d.ts"/>
+/// <reference path="../../../definitions/Q.d.ts"/>
+import Q = require('q');
+import assert = require('assert');
+import mockHelper = require('../../lib/mockHelper');
+import path = require('path');
+import fs = require('fs');
+import tl = require('../../lib/vsts-task-lib/toolRunner');
+
+// Paths aren't the same between compile time and run time. This will need some work
+let realrequire = require;
+function myrequire(module: string): any {
+    return realrequire(path.join(__dirname, "../../../Tasks/Ant/node_modules", module));
+}
+require = <typeof require>myrequire;
+import {CodeCoverageEnablerFactory} from 'codecoverage-tools/codecoveragefactory';
+
+function setResponseFile(name: string) {
+    process.env['MOCK_RESPONSES'] = path.join(__dirname, name);
+}
+
+describe('Code Coverage enable tool tests', function () {
+    this.timeout(20000);
+
+    let data = path.join(__dirname, "data");
+    let buildProps: { [key: string]: string } = {};
+    buildProps['classfilter'] = "+:com.abc,-:com.xyz"
+    buildProps['classfilesdirectories'] = "cfd";
+    buildProps['sourcedirectories'] = "sd";
+    buildProps['summaryfile'] = "coverage.xml";
+    buildProps['reportdirectory'] = path.join(data, "CCReport43F6D5EF");
+    buildProps['ccreporttask'] = "CodeCoverage_9064e1d0"
+    buildProps['reportbuildfile'] = path.join(data, "CCReportBuildA4D283EG.xml");
+
+    before((done) => {
+        Q.longStackSupport = true;
+        done();
+    });
+
+    after(function () {
+    });
+
+    /* Maven build tool - Code Coverage */
+    it('Maven single module build file with Jacoco CC', (done) => {
+        let buildFile = path.join(data, "single_module_pom.xml");
+        buildProps['buildfile'] = buildFile;
+
+        let ccEnabler = new CodeCoverageEnablerFactory().getTool("maven", "jacoco");
+        ccEnabler.enableCodeCoverage(buildProps).then(function () {
+            let content = fs.readFileSync(buildFile, "utf-8");
+            assert.notEqual(content.indexOf(`<include>**/com/abc.class</include>`), -1, "Include filter must be present");
+            assert.notEqual(content.indexOf(`<exclude>**/com/xyz.class</exclude>`), -1, "Exclude filter must be present");
+            assert.notEqual(content.indexOf(`jacoco-maven-plugin`), -1, "Jacoco maven plugin must be enabled");
+            done();
+        }).catch(function (err) {
+            done(err);
+        });
+    })
+
+    it('Maven multi module build file with Jacoco CC', (done) => {
+        let buildFile = path.join(data, "multi_module_pom.xml");
+        buildProps['buildfile'] = buildFile;
+
+        let ccEnabler = new CodeCoverageEnablerFactory().getTool("maven", "jacoco");
+        ccEnabler.enableCodeCoverage(buildProps).then(function (resp) {
+            let content = fs.readFileSync(buildFile, "utf-8");
+            assert.notEqual(content.indexOf(`<include>**/com/abc.class</include>`), -1, "Include filter must be present");
+            assert.notEqual(content.indexOf(`<exclude>**/com/xyz.class</exclude>`), -1, "Exclude filter must be present");
+            assert.notEqual(content.indexOf(`jacoco-maven-plugin`), -1, "Jacoco maven plugin must be enabled");
+            done();
+        }).catch(function (err) {
+            done(err);
+        });
+    })
+
+    it('Maven single module build file with Cobertura CC', (done) => {
+        let buildFile = path.join(data, "single_module_pom.xml");
+        buildProps['buildfile'] = buildFile;
+
+        let ccEnabler = new CodeCoverageEnablerFactory().getTool("maven", "cobertura");
+        ccEnabler.enableCodeCoverage(buildProps).then(function (resp) {
+            let content = fs.readFileSync(buildFile, "utf-8");
+            assert.notEqual(content.indexOf(`<include>com/abc.class</include>`), -1, "Include filter must be present");
+            assert.notEqual(content.indexOf(`<exclude>com/xyz.class</exclude>`), -1, "Exclude filter must be present");
+            assert.notEqual(content.indexOf(`cobertura-maven-plugin`), -1, "Cobertura maven plugin must be enabled");
+            done();
+        }).catch(function (err) {
+            done(err);
+        });
+    })
+
+    it('Maven multi module build file with Cobertura CC', (done) => {
+        let buildFile = path.join(data, "multi_module_pom.xml");
+        buildProps['buildfile'] = buildFile;
+
+        let ccEnabler = new CodeCoverageEnablerFactory().getTool("maven", "cobertura");
+        ccEnabler.enableCodeCoverage(buildProps).then(function (resp) {
+            let content = fs.readFileSync(buildFile, "utf-8");
+            assert.notEqual(content.indexOf(`<include>com/abc.class</include>`), -1, "Include filter must be present");
+            assert.notEqual(content.indexOf(`<exclude>com/xyz.class</exclude>`), -1, "Exclude filter must be present");
+            assert.notEqual(content.indexOf(`cobertura-maven-plugin`), -1, "Cobertura maven plugin must be enabled");
+            done();
+        }).catch(function (err) {
+            done(err);
+        });
+    })
+
+    /* Gradle build tool - Code Coverage */
+    it('Gradle single module build file with Jacoco CC', (done) => {
+        let buildFile = path.join(data, "single_module_build.gradle");
+        buildProps['buildfile'] = buildFile;
+
+        let ccEnabler = new CodeCoverageEnablerFactory().getTool("gradle", "jacoco");
+        ccEnabler.enableCodeCoverage(buildProps).then(function (resp) {
+            let content = fs.readFileSync(buildFile, "utf-8");
+            assert.notEqual(content.indexOf(`def jacocoIncludes = ['com/abc.class']`), -1, "Include filter must be present");
+            assert.notEqual(content.indexOf(`def jacocoExcludes = ['com/xyz.class']`), -1, "Exclude filter must be present");
+            assert.notEqual(content.indexOf(`finalizedBy jacocoTestReport`), -1, "Jacoco report task must be present");
+            assert.notEqual(content.indexOf(`apply plugin: 'jacoco'`), -1, "Jacoco gradle plugin must be enabled");
+            done();
+        }).catch(function (err) {
+            done(err);
+        });
+    })
+
+    it('Gradle multi module build file with Jacoco CC', (done) => {
+        let buildFile = path.join(data, "multi_module_build.gradle");
+        buildProps['buildfile'] = buildFile;
+        buildProps['ismultimodule'] = "true";
+
+        let ccEnabler = new CodeCoverageEnablerFactory().getTool("gradle", "jacoco");
+        ccEnabler.enableCodeCoverage(buildProps).then(function (resp) {
+            let content = fs.readFileSync(buildFile, "utf-8");
+            assert.notEqual(content.indexOf(`def jacocoExcludes = ['com/xyz.class']`), -1, "Include filter must be present");
+            assert.notEqual(content.indexOf(`def jacocoIncludes = ['com/abc.class']`), -1, "Exclude filter must be present");
+            assert.notEqual(content.indexOf(`jacocoRootReport`), -1, "Jacoco task must be enabled");
+            done();
+        }).catch(function (err) {
+            done(err);
+        });
+    })
+
+    it('Gradle single module build file with Cobertura CC', (done) => {
+        let buildFile = path.join(data, "single_module_build.gradle");
+        buildProps['buildfile'] = buildFile;
+
+        let ccEnabler = new CodeCoverageEnablerFactory().getTool("gradle", "cobertura");
+        ccEnabler.enableCodeCoverage(buildProps).then(function (resp) {
+            let content = fs.readFileSync(buildFile, "utf-8");
+            assert.notEqual(content.indexOf(`cobertura.coverageIncludes = ['.*com.abc']`), -1, "Include filter must be present");
+            assert.notEqual(content.indexOf(`cobertura.coverageExcludes = ['.*com.xyz']`), -1, "Exclude filter must be present");
+            assert.notEqual(content.indexOf(`net.saliman:gradle-cobertura-plugin`), -1, "Cobertura Plugin must be present");
+            done();
+        }).catch(function (err) {
+            done(err);
+        });
+    })
+
+    it('Gradle multi module build file with Cobertura CC', (done) => {
+        let buildFile = path.join(data, "multi_module_build.gradle");
+        buildProps['buildfile'] = buildFile;
+        buildProps['ismultimodule'] = "true";
+
+        let ccEnabler = new CodeCoverageEnablerFactory().getTool("gradle", "cobertura");
+        ccEnabler.enableCodeCoverage(buildProps).then(function (resp) {
+            let content = fs.readFileSync(buildFile, "utf-8");
+            assert.notEqual(content.indexOf(`cobertura.coverageIncludes = ['.*com.abc']`), -1, "Include filter must be present");
+            assert.notEqual(content.indexOf(`cobertura.coverageExcludes = ['.*com.xyz']`), -1, "Exclude filter must be present");
+            assert.notEqual(content.indexOf(`net.saliman:gradle-cobertura-plugin`), -1, "Cobertura Plugin must be present");
+            done();
+        }).catch(function (err) {
+            done(err);
+        });
+    })
+
+    /* Ant build tool - Code Coverage */
+    it('Ant build file with Jacoco CC', (done) => {
+        let buildFile = path.join(data, "ant_build.xml");
+        buildProps['buildfile'] = buildFile;
+
+        let ccEnabler = new CodeCoverageEnablerFactory().getTool("ant", "jacoco");
+        ccEnabler.enableCodeCoverage(buildProps).then(function (resp) {
+            let content = fs.readFileSync(buildFile, "utf-8");
+            assert.notEqual(content.indexOf(`excludes="**/com/xyz.class"`), -1, "Exclude filter must be present");
+            assert.notEqual(content.indexOf(`includes="**/com/abc.class"`), -1, "Include filter must be present");
+            assert.notEqual(content.indexOf(`jacoco:coverage destfile="jacoco.exec"`), -1, "Jacoco Plugin must be present");
+            done();
+        }).catch(function (err) {
+            done(err);
+        });
+    })
+
+    it('Ant build file with Cobertura CC', (done) => {
+        let buildFile = path.join(data, "ant_build.xml");
+        buildProps['buildfile'] = buildFile;
+
+        let ccEnabler = new CodeCoverageEnablerFactory().getTool("ant", "cobertura");
+        ccEnabler.enableCodeCoverage(buildProps).then(function (resp) {
+            let content = fs.readFileSync(buildFile, "utf-8");
+            assert.notEqual(fs.existsSync(path.join(data, buildProps['reportbuildfile'])), true, "Report file must be present");
+            assert.notEqual(content.indexOf(`cobertura-classpath`), -1, "Jacoco Plugin must be present");
+            done();
+        }).catch(function (err) {
+            done(err);
+        });
+    })
+});
\ No newline at end of file
diff --git a/Tests/L0/Common-CodeCoverageEnabler/data/ant_build.xml b/Tests/L0/Common-CodeCoverageEnabler/data/ant_build.xml
new file mode 100644
index 000000000000..aca4cfce6d50
--- /dev/null
+++ b/Tests/L0/Common-CodeCoverageEnabler/data/ant_build.xml
@@ -0,0 +1,38 @@
+<project name="JunitTest" default="test" basedir=".">
+   <property name="testdir" location="test" />
+   <property name="srcdir" location="src" />
+   <property name="libdir" value="lib"/>
+   <property name="reportdir" location="report" />
+   <property name="full-compile" value="true" />
+
+   <path id="classpath.base"/>
+   <path id="classpath.test">
+      <pathelement location="${testdir}" />
+      <pathelement location="${srcdir}" />
+      <path refid="classpath.base" />
+      <pathelement location="lib/junit-4.12.jar" />
+   </path>
+
+   <target name="clean" >
+      <delete verbose="${full-compile}">
+         <fileset dir="${testdir}" includes="**/*.class" />
+         <fileset dir="." includes="**/Testresult*.xml" />
+      </delete>
+   </target>
+
+   <target name="compile" depends="clean">
+     <javac srcdir="${srcdir}" destdir="${testdir}" verbose="${full-compile}">
+       <classpath refid="classpath.test"/>
+     </javac>
+   </target>
+
+   <target name="test" depends="compile">
+    <junit fork="no" haltonfailure="false" printsummary="true" haltonerror="false" showoutput="false">
+         <classpath refid="classpath.test" />
+         <formatter type="plain" usefile="false" />
+         <test name="app.test.UtilTest" outfile="Testresult_UtilTest">
+           <formatter type="xml"/>
+         </test>
+    </junit>
+   </target>
+</project>
\ No newline at end of file
diff --git a/Tests/L0/Common-CodeCoverageEnabler/data/multi_module_build.gradle b/Tests/L0/Common-CodeCoverageEnabler/data/multi_module_build.gradle
new file mode 100644
index 000000000000..817ad287abbd
--- /dev/null
+++ b/Tests/L0/Common-CodeCoverageEnabler/data/multi_module_build.gradle
@@ -0,0 +1,11 @@
+allprojects {
+	repositories {
+        mavenCentral()
+    }
+}
+
+subprojects {
+	
+	apply plugin: 'java'
+
+}
diff --git a/Tests/L0/Common-CodeCoverageEnabler/data/multi_module_pom.xml b/Tests/L0/Common-CodeCoverageEnabler/data/multi_module_pom.xml
new file mode 100644
index 000000000000..db2de4b1ac49
--- /dev/null
+++ b/Tests/L0/Common-CodeCoverageEnabler/data/multi_module_pom.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>com.mlesniak.jacoco</groupId>
+    <artifactId>module-main</artifactId>
+    <version>1.0-SNAPSHOT</version>
+    <packaging>pom</packaging>
+
+    <modules>
+        <module>module-1</module>
+        <module>module-2</module>
+    </modules>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+    <build>
+        <plugins>
+        </plugins>
+    </build>
+
+
+    <dependencies>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.11</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/Tests/L0/Common-CodeCoverageEnabler/data/single_module_build.gradle b/Tests/L0/Common-CodeCoverageEnabler/data/single_module_build.gradle
new file mode 100644
index 000000000000..b2440bd4e36f
--- /dev/null
+++ b/Tests/L0/Common-CodeCoverageEnabler/data/single_module_build.gradle
@@ -0,0 +1,10 @@
+repositories {
+	mavenCentral()
+}
+
+apply plugin: 'java'
+
+dependencies {
+	compile 'log4j:log4j:1.2.17'
+	compile 'junit:junit:4.11'
+}
diff --git a/Tests/L0/Common-CodeCoverageEnabler/data/single_module_pom.xml b/Tests/L0/Common-CodeCoverageEnabler/data/single_module_pom.xml
new file mode 100644
index 000000000000..421944719076
--- /dev/null
+++ b/Tests/L0/Common-CodeCoverageEnabler/data/single_module_pom.xml
@@ -0,0 +1,21 @@
+<!-- This was working file-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>com.mycompany.app</groupId>
+  <artifactId>my-app</artifactId>
+  <packaging>jar</packaging>
+  <version>1.0-SNAPSHOT</version>
+  <name>my-app</name>
+  <url>http://maven.apache.org</url>
+	<build>
+	</build>
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.1</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/Tests/L0/Gradle/_suite.ts b/Tests/L0/Gradle/_suite.ts
index 79468918b1ee..3f57697af842 100644
--- a/Tests/L0/Gradle/_suite.ts
+++ b/Tests/L0/Gradle/_suite.ts
@@ -183,6 +183,7 @@ describe('gradle Suite', function () {
                 done();
             })
             .fail((err) => {
+                console.log(tr.stdout);
                 done(err);
             });
     })
@@ -554,159 +555,6 @@ describe('gradle Suite', function () {
             });
     })
 
-    it('Gradle with jacoco selected should call enable and publish code coverage for a single module project.', (done) => {
-        setResponseFile('gradleCCSingleModule.json');
-
-        var tr = new TaskRunner('Gradle');
-        tr.setInput('wrapperScript', 'gradlew'); // Make that checkPath returns true for this filename in the response file
-        tr.setInput('options', '');
-        tr.setInput('tasks', 'build');
-        tr.setInput('javaHomeSelection', 'JDKVersion');
-        tr.setInput('jdkVersion', 'default');
-        tr.setInput('publishJUnitResults', 'true');
-        tr.setInput('testResultsFiles', '**/build/test-results/TEST-*.xml');
-        tr.setInput('codeCoverageTool', 'JaCoCo');
-
-        tr.run()
-            .then(() => {
-                assert(tr.ran(gradleWrapper + ' properties'), 'it should have run gradlew build');
-                assert(tr.ran(gradleWrapper + ' clean build jacocoTestReport'), 'it should have run clean gradlew build');
-                assert(tr.invokedToolCount == 2, 'should have only run gradle 2 times');
-                assert(tr.stdout.search(/##vso\[codecoverage.enable buildfile=build.gradle;summaryfile=summary.xml;reportdirectory=CCReport43F6D5EF;ismultimodule=false;buildtool=Gradle;codecoveragetool=JaCoCo;\]/) >= 0, 'should have called enable code coverage.');
-                assert(tr.stdout.search(/##vso\[codecoverage.publish codecoveragetool=JaCoCo;summaryfile=CCReport43F6D5EF\\summary.xml;reportdirectory=CCReport43F6D5EF;\]/) >= 0 ||
-                    tr.stdout.search(/##vso\[codecoverage.publish codecoveragetool=JaCoCo;summaryfile=CCReport43F6D5EF\/summary.xml;reportdirectory=CCReport43F6D5EF;\]/) >= 0, 'should have called publish code coverage.');
-                assert(tr.resultWasSet, 'task should have set a result');
-                assert(tr.stderr.length == 0, 'should not have written to stderr');
-                assert(tr.succeeded, 'task should have succeeded');
-                done();
-            })
-            .fail((err) => {
-                done(err);
-            });
-    })
-
-    it('Gradle with jacoco selected should call enable and publish code coverage for a multi module project.', (done) => {
-        setResponseFile('gradleCCMultiModule.json');
-
-        var tr = new TaskRunner('Gradle');
-        tr.setInput('wrapperScript', 'gradlew'); // Make that checkPath returns true for this filename in the response file
-        tr.setInput('options', '');
-        tr.setInput('tasks', 'build');
-        tr.setInput('javaHomeSelection', 'JDKVersion');
-        tr.setInput('jdkVersion', 'default');
-        tr.setInput('publishJUnitResults', 'true');
-        tr.setInput('testResultsFiles', '**/build/test-results/TEST-*.xml');
-        tr.setInput('codeCoverageTool', 'JaCoCo');
-
-        tr.run()
-            .then(() => {
-                assert(tr.ran(gradleWrapper + ' properties'), 'it should have run gradlew build');
-                assert(tr.ran(gradleWrapper + ' clean build jacocoRootReport'), 'it should have run gradlew clean build');
-                assert(tr.invokedToolCount == 2, 'should have only run gradle 2 times');
-                assert(tr.stdout.search(/##vso\[codecoverage.enable buildfile=build.gradle;summaryfile=summary.xml;reportdirectory=CCReport43F6D5EF;ismultimodule=true;buildtool=Gradle;codecoveragetool=JaCoCo;\]/) >= 0, 'should have called enable code coverage.');
-                assert(tr.stdout.search(/##vso\[codecoverage.publish codecoveragetool=JaCoCo;summaryfile=CCReport43F6D5EF\\summary.xml;reportdirectory=CCReport43F6D5EF;\]/) >= 0 ||
-                    tr.stdout.search(/##vso\[codecoverage.publish codecoveragetool=JaCoCo;summaryfile=CCReport43F6D5EF\/summary.xml;reportdirectory=CCReport43F6D5EF;\]/) >= 0, 'should have called publish code coverage.');
-                assert(tr.resultWasSet, 'task should have set a result');
-                assert(tr.stderr.length == 0, 'should not have written to stderr');
-                assert(tr.succeeded, 'task should have succeeded');
-                done();
-            })
-            .fail((err) => {
-                done(err);
-            });
-    })
-
-    it('Gradle with cobertura selected should call enable and publish code coverage.', (done) => {
-        setResponseFile('gradleCCSingleModule.json');
-
-        var tr = new TaskRunner('Gradle');
-        tr.setInput('wrapperScript', 'gradlew'); // Make that checkPath returns true for this filename in the response file
-        tr.setInput('options', '');
-        tr.setInput('tasks', 'build');
-        tr.setInput('javaHomeSelection', 'JDKVersion');
-        tr.setInput('jdkVersion', 'default');
-        tr.setInput('publishJUnitResults', 'true');
-        tr.setInput('testResultsFiles', '**/build/test-results/TEST-*.xml');
-        tr.setInput('codeCoverageTool', 'Cobertura');
-
-        tr.run()
-            .then(() => {
-                assert(tr.ran(gradleWrapper + ' properties'), 'it should have run gradlew build');
-                assert(tr.ran(gradleWrapper + ' clean build cobertura'), 'it should have run gradlew clean build');
-                assert(tr.invokedToolCount == 2, 'should have only run gradle 2 times');
-                assert(tr.stdout.search(/##vso\[codecoverage.enable buildfile=build.gradle;summaryfile=coverage.xml;reportdirectory=CCReport43F6D5EF;ismultimodule=false;buildtool=Gradle;codecoveragetool=Cobertura;\]/) >= 0, 'should have called enable code coverage.');
-                assert(tr.stdout.search(/##vso\[codecoverage.publish codecoveragetool=Cobertura;summaryfile=CCReport43F6D5EF\\coverage.xml;reportdirectory=CCReport43F6D5EF;\]/) >= 0 ||
-                    tr.stdout.search(/##vso\[codecoverage.publish codecoveragetool=Cobertura;summaryfile=CCReport43F6D5EF\/coverage.xml;reportdirectory=CCReport43F6D5EF;\]/) >= 0, 'should have called publish code coverage.');
-                assert(tr.resultWasSet, 'task should have set a result');
-                assert(tr.stderr.length == 0, 'should not have written to stderr');
-                assert(tr.succeeded, 'task should have succeeded');
-                done();
-            })
-            .fail((err) => {
-                done(err);
-            });
-    })
-
-    it('Gradle with jacoco selected and report generation failed should call enable but not publish code coverage.', (done) => {
-        setResponseFile('gradleGood.json');
-
-        var tr = new TaskRunner('Gradle');
-        tr.setInput('wrapperScript', 'gradlew'); // Make that checkPath returns true for this filename in the response file
-        tr.setInput('options', '');
-        tr.setInput('tasks', 'build');
-        tr.setInput('javaHomeSelection', 'JDKVersion');
-        tr.setInput('jdkVersion', 'default');
-        tr.setInput('publishJUnitResults', 'true');
-        tr.setInput('testResultsFiles', '**/build/test-results/TEST-*.xml');
-        tr.setInput('codeCoverageTool', 'JaCoCo');
-
-        tr.run()
-            .then(() => {
-                assert(tr.ran(gradleWrapper + ' properties'), 'it should have run gradlew build');
-                assert(tr.ran(gradleWrapper + ' clean build jacocoTestReport'), 'it should have run gradlew clean build');
-                assert(tr.invokedToolCount == 2, 'should have only run gradle 2 times');
-                assert(tr.stdout.search(/##vso\[codecoverage.enable buildfile=build.gradle;summaryfile=summary.xml;reportdirectory=CCReport43F6D5EF;ismultimodule=false;buildtool=Gradle;codecoveragetool=JaCoCo;\]/) >= 0, 'should have called enable code coverage.');
-                assert(tr.stdout.search(/##vso\[codecoverage.publish\]/) < 0, 'should not have called publish code coverage.');
-                assert(tr.resultWasSet, 'task should have set a result');
-                assert(tr.stderr.length == 0, 'should not have written to stderr');
-                assert(tr.succeeded, 'task should have succeeded');
-                done();
-            })
-            .fail((err) => {
-                done(err);
-            });
-    })
-
-    it('Gradle with cobertura selected and report generation failed should call enable but not publish code coverage.', (done) => {
-        setResponseFile('gradleGood.json');
-
-        var tr = new TaskRunner('Gradle');
-        tr.setInput('wrapperScript', 'gradlew'); // Make that checkPath returns true for this filename in the response file
-        tr.setInput('options', '');
-        tr.setInput('tasks', 'build');
-        tr.setInput('javaHomeSelection', 'JDKVersion');
-        tr.setInput('jdkVersion', 'default');
-        tr.setInput('publishJUnitResults', 'true');
-        tr.setInput('testResultsFiles', '**/build/test-results/TEST-*.xml');
-        tr.setInput('codeCoverageTool', 'Cobertura');
-
-        tr.run()
-            .then(() => {
-                assert(tr.ran(gradleWrapper + ' properties'), 'it should have run gradlew build');
-                assert(tr.ran(gradleWrapper + ' clean build cobertura'), 'it should have run gradlew clean build');
-                assert(tr.invokedToolCount == 2, 'should have only run gradle 2 times');
-                assert(tr.stdout.search(/##vso\[codecoverage.enable buildfile=build.gradle;summaryfile=coverage.xml;reportdirectory=CCReport43F6D5EF;ismultimodule=false;buildtool=Gradle;codecoveragetool=Cobertura;\]/) >= 0, 'should have called enable code coverage.');
-                assert(tr.stdout.search(/##vso\[codecoverage.publish\]/) < 0, 'should not have called publish code coverage.');
-                assert(tr.resultWasSet, 'task should have set a result');
-                assert(tr.stderr.length == 0, 'should not have written to stderr');
-                assert(tr.succeeded, 'task should have succeeded');
-                done();
-            })
-            .fail((err) => {
-                done(err);
-            });
-    })
-
     it('Gradle build with publish test results.', (done) => {
         setResponseFile('gradleGood.json');
 
diff --git a/Tests/L0/Maven/_suite.ts b/Tests/L0/Maven/_suite.ts
index 1eae9b65b47c..13e31c7b7aac 100644
--- a/Tests/L0/Maven/_suite.ts
+++ b/Tests/L0/Maven/_suite.ts
@@ -1028,239 +1028,6 @@ describe('Maven Suite', function () {
             });
     });
 
-    it('maven calls enable code coverage and publish code coverage when jacoco is selected', (done) => {
-        setResponseFile('responseCodeCoverage.json');
-        var tr = new trm.TaskRunner('Maven', true);
-        tr.setInput('mavenVersionSelection', 'default');
-        tr.setInput('mavenPOMFile', 'pom.xml'); // Make that checkPath returns true for this filename in the response file
-        tr.setInput('options', '');
-        tr.setInput('goals', 'package');
-        tr.setInput('javaHomeSelection', 'JDKVersion');
-        tr.setInput('jdkVersion', 'default');
-        tr.setInput('codeCoverageTool', 'JaCoCo');
-        tr.setInput('publishJUnitResults', 'true');
-        tr.setInput('testResultsFiles', '**/TEST-*.xml');
-
-        tr.run()
-            .then(() => {
-                assert(tr.ran('/home/bin/maven/bin/mvn -version'), 'it should have run mvn -version');
-                assert(tr.ran('/home/bin/maven/bin/mvn -f pom.xml clean package'), 'it should have run mvn -f pom.xml clean package');
-                assert(tr.ran('/home/bin/maven/bin/mvn -f pom.xml jacoco:report'), 'it should have run mvn -f pom.xml jacoco:report');
-                // calls maven to generate cc report.
-                assert(tr.invokedToolCount == 3, 'should have only run maven 3 times');
-                assert(tr.resultWasSet, 'task should have set a result');
-                assert(tr.stdout.search(/##vso\[codecoverage.enable buildfile=pom.xml;summaryfile=CCReport43F6D5EF\/jacoco.xml;reportdirectory=CCReport43F6D5EF;reportbuildfile=CCReportPomA4D283EG.xml;buildtool=Maven;codecoveragetool=JaCoCo;\]/) >= 0, 'should have called enable code coverage.');
-                assert(tr.stdout.search(/##vso\[codecoverage.publish codecoveragetool=JaCoCo;summaryfile=CCReport43F6D5EF\/jacoco.xml;reportdirectory=CCReport43F6D5EF;\]/) >= 0, 'should have called publish code coverage.');
-                assert(tr.stderr.length == 0, 'should not have written to stderr');
-                assert(tr.succeeded, 'task should have succeeded');
-                done();
-            })
-            .fail((err) => {
-                assert.fail("should not have thrown error");
-                done(err);
-            });
-    })
-
-    it('maven calls enable code coverage and publish code coverage and sonar analysis when jacoco and sonar analysis is selected', function (done) {
-        // Arrange
-        createTempDirsForSonarQubeTests();
-        var testSrcDir: string = path.join(__dirname, 'data', 'taskreport-valid');
-        var testStgDir: string = path.join(__dirname, '_temp');
-
-        // not a valid PR branch
-        mockHelper.setResponseAndBuildVars(
-            path.join(__dirname, 'responseCodeCoverage.json'),
-            path.join(__dirname, 'new_response.json'),
-            [["build.sourceBranch", "refspull/6/master"], ["build.repository.provider", "TFSGit"],
-                ['build.sourcesDirectory', testSrcDir], ['build.artifactStagingDirectory', testStgDir]]);
-        var responseJsonFilePath: string = path.join(__dirname, 'new_response.json');
-        var responseJsonContent = JSON.parse(fs.readFileSync(responseJsonFilePath, 'utf-8'));
-
-        // Add fields corresponding to responses for mock filesystem operations for the following paths
-        // Staging directories
-        responseJsonContent = mockHelper.setupMockResponsesForPaths(responseJsonContent, listFolderContents(testStgDir));
-        // Test data files
-        responseJsonContent = mockHelper.setupMockResponsesForPaths(responseJsonContent, listFolderContents(testSrcDir));
-
-        // Write and set the newly-changed response file
-        var newResponseFilePath: string = path.join(__dirname, this.test.title + '_response.json');
-        fs.writeFileSync(newResponseFilePath, JSON.stringify(responseJsonContent));
-        setResponseFile(path.basename(newResponseFilePath));
-
-        var tr: trm.TaskRunner = setupDefaultMavenTaskRunner();
-        tr.setInput('sqAnalysisEnabled', 'true');
-        tr.setInput('sqConnectedServiceName', 'ID1');
-        tr.setInput('codeCoverageTool', 'JaCoCo');
-        tr.setInput('publishJUnitResults', 'true');
-
-        tr.run()
-            .then(() => {
-                assert(tr.ran('/home/bin/maven/bin/mvn -version'), 'it should have run mvn -version');
-                assert(tr.ran('/home/bin/maven/bin/mvn -f pom.xml jacoco:report'), 'it should have run mvn -f pom.xml jacoco:report');
-                assert(tr.ran('/home/bin/maven/bin/mvn -f pom.xml clean package -Dsonar.host.url=http://sonarqubeserver:9000 -Dsonar.login=uname -Dsonar.password=pword -Dsonar.jacoco.reportPath=CCReport43F6D5EF\/jacoco.exec sonar:sonar'), 'it should have run SQ analysis');
-                // calls maven to generate cc report.
-                assert(tr.invokedToolCount == 3, 'should have only run maven 3 times');
-                assert(tr.resultWasSet, 'task should have set a result');
-                assert(tr.stdout.search(/##vso\[codecoverage.enable buildfile=pom.xml;summaryfile=CCReport43F6D5EF\/jacoco.xml;reportdirectory=CCReport43F6D5EF;reportbuildfile=CCReportPomA4D283EG.xml;buildtool=Maven;codecoveragetool=JaCoCo;\]/) >= 0, 'should have called enable code coverage.');
-                assert(tr.stdout.search(/##vso\[codecoverage.publish codecoveragetool=JaCoCo;summaryfile=CCReport43F6D5EF\/jacoco.xml;reportdirectory=CCReport43F6D5EF;\]/) >= 0, 'should have called publish code coverage.');
-                assert(tr.stderr.length == 0, 'should not have written to stderr');
-                assert(tr.succeeded, 'task should have succeeded');
-                done();
-            })
-            .fail((err) => {
-                console.log(tr.stdout);
-                console.log(tr.stderr);
-                console.log(err);
-                assert.fail("should not have thrown error");
-                done(err);
-            });
-    })
-
-    it('maven calls enable code coverage and not publish code coverage when jacoco is selected and report generation failed', (done) => {
-        setResponseFile('response.json');
-        var tr = new trm.TaskRunner('Maven', true);
-        tr.setInput('mavenVersionSelection', 'default');
-        tr.setInput('mavenPOMFile', 'pom.xml'); // Make that checkPath returns true for this filename in the response file
-        tr.setInput('options', '');
-        tr.setInput('goals', 'package');
-        tr.setInput('javaHomeSelection', 'JDKVersion');
-        tr.setInput('jdkVersion', 'default');
-        tr.setInput('codeCoverageTool', 'JaCoCo');
-        tr.setInput('publishJUnitResults', 'true');
-        tr.setInput('testResultsFiles', '**/TEST-*.xml');
-
-        tr.run()
-            .then(() => {
-                assert(tr.ran('/home/bin/maven/bin/mvn -version'), 'it should have run mvn -version');
-                assert(tr.ran('/home/bin/maven/bin/mvn -f pom.xml clean package'), 'it should have run mvn -f pom.xml clean package');
-                assert(tr.ran('/home/bin/maven/bin/mvn -f pom.xml jacoco:report'), 'it should have run mvn -f pom.xml jacoco:report');
-                // calls maven to generate cc report.
-                assert(tr.invokedToolCount == 3, 'should have only run maven 3 times');
-                assert(tr.resultWasSet, 'task should have set a result');
-                assert(tr.stdout.search(/##vso\[codecoverage.enable buildfile=pom.xml;summaryfile=CCReport43F6D5EF\/jacoco.xml;reportdirectory=CCReport43F6D5EF;reportbuildfile=CCReportPomA4D283EG.xml;buildtool=Maven;codecoveragetool=JaCoCo;\]/) >= 0, 'should have called enable code coverage.');
-                assert(tr.stdout.search(/##vso\[codecoverage.publish\]/) < 0, 'should not have called publish code coverage.');
-                assert(tr.stderr.length == 0, 'should not have written to stderr');
-                assert(tr.succeeded, 'task should have succeeded');
-                done();
-            })
-            .fail((err) => {
-                assert.fail("should not have thrown error");
-                done(err);
-            });
-    })
-
-    it('maven calls enable code coverage and publish code coverage when cobertura is selected', (done) => {
-        setResponseFile('responseCodeCoverage.json');
-        var tr = new trm.TaskRunner('Maven', true);
-        tr.setInput('mavenVersionSelection', 'default');
-        tr.setInput('mavenPOMFile', 'pom.xml'); // Make that checkPath returns true for this filename in the response file
-        tr.setInput('options', '');
-        tr.setInput('goals', 'package');
-        tr.setInput('javaHomeSelection', 'JDKVersion');
-        tr.setInput('jdkVersion', 'default');
-        tr.setInput('codeCoverageTool', 'Cobertura');
-        tr.setInput('publishJUnitResults', 'true');
-        tr.setInput('testResultsFiles', '**/TEST-*.xml');
-
-        tr.run()
-            .then(() => {
-                assert(tr.ran('/home/bin/maven/bin/mvn -version'), 'it should have run mvn -version');
-                assert(tr.ran('/home/bin/maven/bin/mvn -f pom.xml clean package'), 'it should have run mvn -f pom.xml clean package');
-                assert(tr.invokedToolCount == 2, 'should have only run maven 2 times');
-                assert(tr.resultWasSet, 'task should have set a result');
-                assert(tr.stdout.search(/##vso\[codecoverage.enable buildfile=pom.xml;summaryfile=target\/site\/cobertura\/coverage.xml;reportdirectory=target\/site\/cobertura;reportbuildfile=CCReportPomA4D283EG.xml;buildtool=Maven;codecoveragetool=Cobertura;\]/) >= 0, 'should have called enable code coverage.');
-                assert(tr.stdout.search(/##vso\[codecoverage.publish codecoveragetool=Cobertura;summaryfile=target\/site\/cobertura\/coverage.xml;reportdirectory=target\/site\/cobertura;\]/) >= 0, 'should have called publish code coverage.');
-                assert(tr.stderr.length == 0, 'should not have written to stderr');
-                assert(tr.succeeded, 'task should have succeeded');
-                done();
-            })
-            .fail((err) => {
-                assert.fail("should not have thrown error");
-                done(err);
-            });
-    })
-
-    it('maven calls enable code coverage and publish code coverage and sonar analysis when cobertura is selected and sonar analysis enabled', function (done) {
-        // Arrange
-        createTempDirsForSonarQubeTests();
-        var testSrcDir: string = path.join(__dirname, 'data', 'taskreport-valid');
-        var testStgDir: string = path.join(__dirname, '_temp');
-
-        // not a valid PR branch
-        mockHelper.setResponseAndBuildVars(
-            path.join(__dirname, 'responseCodeCoverage.json'),
-            path.join(__dirname, 'new_response.json'),
-            [["build.sourceBranch", "refspull/6/master"], ["build.repository.provider", "TFSGit"],
-                ['build.sourcesDirectory', testSrcDir], ['build.artifactStagingDirectory', testStgDir]]);
-        var responseJsonFilePath: string = path.join(__dirname, 'new_response.json');
-        var responseJsonContent = JSON.parse(fs.readFileSync(responseJsonFilePath, 'utf-8'));
-
-        // Add fields corresponding to responses for mock filesystem operations for the following paths
-        // Staging directories
-        responseJsonContent = mockHelper.setupMockResponsesForPaths(responseJsonContent, listFolderContents(testStgDir));
-        // Test data files
-        responseJsonContent = mockHelper.setupMockResponsesForPaths(responseJsonContent, listFolderContents(testSrcDir));
-
-        // Write and set the newly-changed response file
-        var newResponseFilePath: string = path.join(__dirname, this.test.title + '_response.json');
-        fs.writeFileSync(newResponseFilePath, JSON.stringify(responseJsonContent));
-        setResponseFile(path.basename(newResponseFilePath));
-
-        var tr: trm.TaskRunner = setupDefaultMavenTaskRunner();
-        tr.setInput('sqAnalysisEnabled', 'true');
-        tr.setInput('sqConnectedServiceName', 'ID1');
-        tr.setInput('codeCoverageTool', 'Cobertura');
-        tr.setInput('publishJUnitResults', 'true');
-
-        tr.run()
-            .then(() => {
-                assert(tr.ran('/home/bin/maven/bin/mvn -version'), 'it should have run mvn -version');
-                assert(tr.ran('/home/bin/maven/bin/mvn -f pom.xml clean package -Dsonar.host.url=http://sonarqubeserver:9000 -Dsonar.login=uname -Dsonar.password=pword sonar:sonar'), 'it should have run SQ analysis');
-                assert(tr.invokedToolCount == 2, 'should have only run maven 2 times');
-                assert(tr.resultWasSet, 'task should have set a result');
-                assert(tr.stdout.search(/##vso\[codecoverage.enable buildfile=pom.xml;summaryfile=target\/site\/cobertura\/coverage.xml;reportdirectory=target\/site\/cobertura;reportbuildfile=CCReportPomA4D283EG.xml;buildtool=Maven;codecoveragetool=Cobertura;\]/) >= 0, 'should have called enable code coverage.');
-                assert(tr.stdout.search(/##vso\[codecoverage.publish codecoveragetool=Cobertura;summaryfile=target\/site\/cobertura\/coverage.xml;reportdirectory=target\/site\/cobertura;\]/) >= 0, 'should have called publish code coverage.');
-                assert(tr.stderr.length == 0, 'should not have written to stderr');
-                assert(tr.succeeded, 'task should have succeeded');
-                done();
-            })
-            .fail((err) => {
-                assert.fail("should not have thrown error");
-                done(err);
-            });
-    })
-
-    it('maven calls enable code coverage and not publish code coverage when cobertura is selected and report generation failed', (done) => {
-        setResponseFile('response.json');
-        var tr = new trm.TaskRunner('Maven', true);
-        tr.setInput('mavenVersionSelection', 'default');
-        tr.setInput('mavenPOMFile', 'pom.xml'); // Make that checkPath returns true for this filename in the response file
-        tr.setInput('options', '');
-        tr.setInput('goals', 'package');
-        tr.setInput('javaHomeSelection', 'JDKVersion');
-        tr.setInput('jdkVersion', 'default');
-        tr.setInput('codeCoverageTool', 'Cobertura');
-        tr.setInput('publishJUnitResults', 'true');
-        tr.setInput('testResultsFiles', '**/TEST-*.xml');
-
-        tr.run()
-            .then(() => {
-                assert(tr.ran('/home/bin/maven/bin/mvn -version'), 'it should have run mvn -version');
-                assert(tr.ran('/home/bin/maven/bin/mvn -f pom.xml clean package'), 'it should have run mvn -f pom.xml clean package');
-                assert(tr.invokedToolCount == 2, 'should have only run maven 2 times');
-                assert(tr.resultWasSet, 'task should have set a result');
-                assert(tr.stdout.search(/##vso\[codecoverage.enable buildfile=pom.xml;summaryfile=target\/site\/cobertura\/coverage.xml;reportdirectory=target\/site\/cobertura;reportbuildfile=CCReportPomA4D283EG.xml;buildtool=Maven;codecoveragetool=Cobertura;\]/) >= 0, 'should have called enable code coverage.');
-                assert(tr.stdout.search(/##vso\[codecoverage.publish\]/) < 0, 'should not have called publish code coverage.');
-                assert(tr.stderr.length == 0, 'should not have written to stderr');
-                assert(tr.succeeded, 'task should have succeeded');
-                done();
-            })
-            .fail((err) => {
-                assert.fail("should not have thrown error");
-                done(err);
-            });
-    })
-
     it('Maven build with publish test results', (done) => {
         setResponseFile('response.json');
         var tr = new trm.TaskRunner('Maven', true);
diff --git a/common.json b/common.json
index 253bff47b5ca..bd01012a82d6 100644
--- a/common.json
+++ b/common.json
@@ -96,5 +96,23 @@
             "module": "nuget-task-common",
             "dest": "node_modules"  
         }
+    ],
+    "Gradle" : [
+        {
+            "module": "codecoverage-tools",
+            "dest": "node_modules"  
+        }
+    ],
+    "Maven" : [
+        {
+            "module": "codecoverage-tools",
+            "dest": "node_modules"  
+        }
+    ],
+    "Ant" : [
+        {
+            "module": "codecoverage-tools",
+            "dest": "node_modules"  
+        }
     ]
 }
diff --git a/definitions/codecoveragefactory.d.ts b/definitions/codecoveragefactory.d.ts
new file mode 100644
index 000000000000..0161b27b2548
--- /dev/null
+++ b/definitions/codecoveragefactory.d.ts
@@ -0,0 +1,19 @@
+/// <reference path="./Q.d.ts" />
+
+declare module 'codecoverage-tools/codecoveragefactory' {
+    import * as Q from "q";
+
+    export interface ICodeCoverageEnabler {
+        enableCodeCoverage(ccProps: {
+            [name: string]: string;
+        }): Q.Promise<boolean>;
+    }
+
+    export interface ICodeCoverageEnablerFactory {
+        getTool(buildTool: string, ccTool: string): ICodeCoverageEnabler;
+    }
+
+    export class CodeCoverageEnablerFactory implements ICodeCoverageEnablerFactory {
+        getTool(buildTool: string, ccTool: string): ICodeCoverageEnabler;
+    }
+}
diff --git a/definitions/fs-extra.d.ts b/definitions/fs-extra.d.ts
new file mode 100644
index 000000000000..01a74d0e214d
--- /dev/null
+++ b/definitions/fs-extra.d.ts
@@ -0,0 +1,88 @@
+// Generated by typings
+// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/2c5c3520d341526c54ca64ca3245d2569dce1d6e/fs-extra/fs-extra.d.ts
+declare module "fs-extra" {
+    export * from "fs";
+
+	export function copy(src: string, dest: string, callback?: (err: Error) => void): void;
+	export function copy(src: string, dest: string, filter: CopyFilter, callback?: (err: Error) => void): void;
+	export function copy(src: string, dest: string, options: CopyOptions, callback?: (err: Error) => void): void;
+
+	export function copySync(src: string, dest: string): void;
+	export function copySync(src: string, dest: string, filter: CopyFilter): void;
+	export function copySync(src: string, dest: string, options: CopyOptions): void;
+
+	export function createFile(file: string, callback?: (err: Error) => void): void;
+	export function createFileSync(file: string): void;
+
+	export function mkdirs(dir: string, callback?: (err: Error) => void): void;
+	export function mkdirp(dir: string, callback?: (err: Error) => void): void;
+	export function mkdirs(dir: string, options?: MkdirOptions, callback?: (err: Error) => void): void;
+	export function mkdirp(dir: string, options?: MkdirOptions, callback?: (err: Error) => void): void;
+	export function mkdirsSync(dir: string, options?: MkdirOptions): void;
+	export function mkdirpSync(dir: string, options?: MkdirOptions): void;
+
+	export function outputFile(file: string, data: any, callback?: (err: Error) => void): void;
+	export function outputFileSync(file: string, data: any): void;
+
+	export function outputJson(file: string, data: any, callback?: (err: Error) => void): void;
+	export function outputJSON(file: string, data: any, callback?: (err: Error) => void): void;
+	export function outputJsonSync(file: string, data: any): void;
+	export function outputJSONSync(file: string, data: any): void;
+
+	export function readJson(file: string, callback: (err: Error, jsonObject: any) => void): void;
+	export function readJson(file: string, options: OpenOptions, callback: (err: Error, jsonObject: any) => void): void;
+	export function readJSON(file: string, callback: (err: Error, jsonObject: any) => void): void;
+	export function readJSON(file: string, options: OpenOptions, callback: (err: Error, jsonObject: any) => void): void;
+
+	export function readJsonSync(file: string, options?: OpenOptions): any;
+	export function readJSONSync(file: string, options?: OpenOptions): any;
+
+	export function remove(dir: string, callback?: (err: Error) => void): void;
+	export function removeSync(dir: string): void;
+
+	export function writeJson(file: string, object: any, callback?: (err: Error) => void): void;
+	export function writeJson(file: string, object: any, options?: OpenOptions, callback?: (err: Error) => void): void;
+	export function writeJSON(file: string, object: any, callback?: (err: Error) => void): void;
+	export function writeJSON(file: string, object: any, options?: OpenOptions, callback?: (err: Error) => void): void;
+
+	export function writeJsonSync(file: string, object: any, options?: OpenOptions): void;
+	export function writeJSONSync(file: string, object: any, options?: OpenOptions): void;
+
+    export function ensureDir(path: string, cb: (err: Error) => void): void;
+    export function ensureDirSync(path: string): void;
+
+	export function ensureFile(path: string, cb: (err: Error) => void): void;
+	export function ensureFileSync(path: string): void;
+
+	export function ensureLink(path: string, cb: (err: Error) => void): void;
+	export function ensureLinkSync(path: string): void;
+
+	export function ensureSymlink(path: string, cb: (err: Error) => void): void;
+	export function ensureSymlinkSync(path: string): void;
+
+    export function emptyDir(path: string, callback?: (err: Error) => void): void;
+    export function emptyDirSync(path: string): boolean;
+
+    export interface CopyFilterFunction {
+		(src: string): boolean
+	}
+
+	export type CopyFilter = CopyFilterFunction | RegExp;
+
+	export interface CopyOptions {
+		clobber?: boolean
+		preserveTimestamps?: boolean
+        dereference?: boolean
+		filter?: CopyFilter
+	}
+
+	export interface OpenOptions {
+		encoding?: string;
+		flag?: string;
+	}
+
+	export interface MkdirOptions {
+		fs?: any;
+		mode?: number;
+	}
+}
diff --git a/definitions/string.d.ts b/definitions/string.d.ts
new file mode 100644
index 000000000000..65ab17c1c6af
--- /dev/null
+++ b/definitions/string.d.ts
@@ -0,0 +1,131 @@
+// Generated by typings
+// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/56295f5058cac7ae458540423c50ac2dcf9fc711/string/string.d.ts
+interface StringJS {
+	length: number;
+	
+	s: string;
+	
+	between(left: string, right?: string): StringJS;
+	
+	camelize(): StringJS;
+	
+	capitalize(): StringJS;
+	
+	chompLeft(prefix: string): StringJS;
+	
+	chompRight(suffix: string): StringJS;
+	
+	collapseWhitespace(): StringJS;
+	
+	contains(ss: string): boolean;
+	
+	count(substring: string): number;
+	
+	dasherize(): StringJS;
+	
+	decodeHTMLEntities(): StringJS;
+	
+	endsWith(ss: string): boolean;
+	
+	escapeHTML(): StringJS;
+	
+	ensureLeft(prefix: string): StringJS;
+	
+	ensureRight(suffix: string): StringJS;
+	
+	humanize(): StringJS;
+	
+	include(ss: string): boolean;
+	
+	isAlpha(): boolean;
+	
+	isAlphaNumeric(): boolean;
+	
+	isEmpty(): boolean;
+	
+	isLower(): boolean;
+	
+	isNumeric(): boolean;
+	
+	isUpper(): boolean;
+	
+	latinise(): StringJS;
+	
+	left(n: number): StringJS;
+	
+	lines(): string[];
+	
+	pad(len: number, char?: string|number): StringJS;
+	
+	padLeft(len: number, char?: string|number): StringJS;
+	
+	padRight(len: number, char?: string|number): StringJS;
+	
+	parseCSV(delimiter?: string, qualifier?: string, escape?: string, lineDelimiter?: string): string[];
+	
+	repeat(n: number): StringJS;
+	
+	replaceAll(ss: string, newStr: string): StringJS;
+	
+	strip(...strings: string[]): StringJS;
+	
+	right(n: number): StringJS;
+	
+	setValue(string: any): StringJS;
+	
+	slugify(): StringJS;
+	
+	startsWith(prefix: string): boolean;
+	
+	stripPunctuation(): StringJS;
+	
+	stripTags(...tags: string[]): StringJS;
+	
+	template(values: Object, open?: string, close?: string): StringJS;
+	
+	times(n: number): StringJS;
+	
+	toBoolean(): boolean;
+	
+	toCSV(delimiter?: string, qualifier?: string): StringJS;
+	toCSV(options: {
+		delimiter?: string,
+		qualifier?: string,
+		escape?: string,
+		encloseNumbers?: boolean,
+		keys?: boolean
+	}): StringJS;
+	
+	toFloat(precision?: number): number;
+	
+	toInt(): number;
+	
+	toInteger(): number;
+	
+	toString(): string;
+	
+	trim(): StringJS;
+	
+	trimLeft(): StringJS;
+	
+	trimRight(): StringJS;
+	
+	truncate(length: number, chars?: string): StringJS;
+	
+	underscore(): StringJS;
+	
+	unescapeHTML(): StringJS;
+	
+	wrapHTML(element?: string, attributes?: Object): StringJS;
+}
+
+declare module "string" {
+	var S: {
+		(o: any): StringJS;
+		VERSION: string;
+		TMPL_OPEN: string;
+		TMPL_CLOSE: string;
+	}
+	
+	export = S;
+}