Onboarding build optimization incl Qual Control

Sonar fixes, incremental build enhancements and Quality control mechanism integration.

Change-Id: I118d7fc0cc50c1eddb94137310c00afaaa3aaffb
Issue-ID: SDC-1189
Signed-off-by: GAUTAMS <gautams@amdocs.com>
diff --git a/openecomp-be/tools/compile-helper-plugin/pom.xml b/openecomp-be/tools/compile-helper-plugin/pom.xml
index 3891558..73513f6 100644
--- a/openecomp-be/tools/compile-helper-plugin/pom.xml
+++ b/openecomp-be/tools/compile-helper-plugin/pom.xml
@@ -14,7 +14,12 @@
         <version>1.2.0-SNAPSHOT</version>
         <relativePath>../../../onboarding</relativePath>
     </parent>
-
+    <properties>
+        <skipPMD>true</skipPMD>
+        <classes>classes/**/*.class</classes>
+        <mavenStatus>maven-status/**</mavenStatus>
+        <skipTestRun>true</skipTestRun>
+    </properties>
     <dependencies>
         <dependency>
             <groupId>org.apache.maven</groupId>
diff --git a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/BuildHelper.java b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/BuildHelper.java
new file mode 100644
index 0000000..42f3166
--- /dev/null
+++ b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/BuildHelper.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright © 2018 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on a "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openecomp.sdc.onboarding;
+
+import static org.openecomp.sdc.onboarding.Constants.JAVA_EXT;
+import static org.openecomp.sdc.onboarding.Constants.UNICORN;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.UncheckedIOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.RecursiveTask;
+import java.util.stream.Collectors;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.project.MavenProject;
+
+class BuildHelper {
+
+    private BuildHelper() {
+        // donot remove.
+    }
+
+    static long getChecksum(File file, String fileType) {
+        try {
+            return readSources(file, fileType).hashCode();
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
+    static String getSourceChecksum(String data, String hashType) throws NoSuchAlgorithmException {
+        MessageDigest md = MessageDigest.getInstance(hashType);
+        md.update(data.getBytes());
+        byte[] hashBytes = md.digest();
+
+        StringBuffer buffer = new StringBuffer();
+        for (byte hashByte : hashBytes) {
+            buffer.append(Integer.toString((hashByte & 0xff) + 0x100, 16).substring(1));
+        }
+        return buffer.toString();
+    }
+
+
+    private static Map<String, String> readSources(File file, String fileType) throws IOException {
+        Map<String, String> source = new HashMap<>();
+        if (file.exists()) {
+            List<File> list = Files.walk(Paths.get(file.getAbsolutePath()))
+                                   .filter(JAVA_EXT.equals(fileType) ? BuildHelper::isRegularJavaFile :
+                                                   Files::isRegularFile).map(p -> p.toFile())
+                                   .collect(Collectors.toList());
+            source.putAll(ForkJoinPool.commonPool()
+                                      .invoke(new FileReadTask(list.toArray(new File[0]), file.getAbsolutePath())));
+        }
+        return source;
+    }
+
+    private static boolean isRegularJavaFile(Path path) {
+        File file = path.toFile();
+        return file.isFile() && file.getName().endsWith(JAVA_EXT);
+    }
+
+    private static String getData(File file, byte[] buffer) {
+        try (FileInputStream fis = new FileInputStream(file);
+             BufferedInputStream bis = new BufferedInputStream(fis, 64 * 1024)) {
+            bis.read(buffer, 0, ((int) file.length()));
+            if (file.getAbsolutePath().contains(File.separator + "generated-sources" + File.separator)) {
+                StringBuffer sb = new StringBuffer();
+                List<String> coll = Files.readAllLines(file.toPath());
+                for (String s : coll) {
+                    if (s != null && !s.trim().startsWith("/") && !s.trim().startsWith("*")) {
+                        sb.append(s);
+                    }
+                }
+                return sb.toString();
+            }
+        } catch (IOException ioe) {
+            throw new UncheckedIOException(ioe);
+        }
+        return new String(buffer, 0, ((int) file.length()));
+    }
+
+
+    private static class FileReadTask extends RecursiveTask<Map<String, String>> {
+
+        Map<String, String> store = new HashMap<>();
+        private byte[] buffer = new byte[1024 * 1024];
+        File[] files;
+        String pathPrefix;
+        private final int MAX_FILES = 10;
+
+        FileReadTask(File[] files, String pathPrefix) {
+            this.files = files;
+            this.pathPrefix = pathPrefix;
+        }
+
+        @Override
+        protected Map<String, String> compute() {
+            if (files.length > MAX_FILES) {
+                FileReadTask task1 = new FileReadTask(Arrays.copyOfRange(files, 0, files.length / 2), pathPrefix);
+                FileReadTask task2 =
+                        new FileReadTask(Arrays.copyOfRange(files, files.length / 2, files.length), pathPrefix);
+                task1.fork();
+                task2.fork();
+                store.putAll(task1.join());
+                store.putAll(task2.join());
+            } else {
+                for (File toRead : files) {
+                    store.put(toRead.getAbsolutePath().substring(pathPrefix.length()), getData(toRead, buffer));
+                }
+            }
+
+            return store;
+        }
+    }
+
+    static Optional<String> getArtifactPathInLocalRepo(String repoPath, MavenProject project, byte[] sourceChecksum)
+            throws MojoFailureException {
+
+        URI uri = null;
+        try {
+            uri = new URI(repoPath + (project.getGroupId().replace('.', '/')) + '/' + project.getArtifactId() + '/'
+                                  + project.getVersion());
+        } catch (URISyntaxException e) {
+            throw new MojoFailureException(e.getMessage());
+        }
+        File f = new File(uri);
+        File[] list = f.listFiles(t -> t.getName().equals(project.getArtifactId() + "-" + project.getVersion() + "."
+                                                                  + project.getPackaging()));
+        if (list != null && list.length > 0) {
+            File checksumFile = new File(list[0].getParentFile(), project.getBuild().getFinalName() + "." + UNICORN);
+            try {
+                if (checksumFile.exists() && Arrays.equals(sourceChecksum, Files.readAllBytes(checksumFile.toPath()))) {
+                    return Optional.of(list[0].getAbsolutePath());
+                }
+            } catch (IOException e) {
+                throw new UncheckedIOException(e);
+            }
+        }
+        return Optional.empty();
+    }
+
+    static <T> Optional<T> readState(String fileName, Class<T> clazz) {
+        try (InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName);
+             ObjectInputStream ois = new ObjectInputStream(is)) {
+            return Optional.of(clazz.cast(ois.readObject()));
+        } catch (Exception ignored) {
+            //ignore. it is taken care.
+            return Optional.empty();
+        }
+    }
+
+}
diff --git a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/BuildState.java b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/BuildState.java
index 888622f..17ff7c9 100644
--- a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/BuildState.java
+++ b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/BuildState.java
@@ -16,7 +16,16 @@
 
 package org.openecomp.sdc.onboarding;
 
+import static org.openecomp.sdc.onboarding.BuildHelper.readState;
+import static org.openecomp.sdc.onboarding.Constants.ANSI_COLOR_RESET;
+import static org.openecomp.sdc.onboarding.Constants.ANSI_YELLOW;
+import static org.openecomp.sdc.onboarding.Constants.FULL_BUILD_DATA;
+import static org.openecomp.sdc.onboarding.Constants.FULL_RESOURCE_BUILD_DATA;
+import static org.openecomp.sdc.onboarding.Constants.JAR;
+import static org.openecomp.sdc.onboarding.Constants.MODULE_BUILD_DATA;
 import static org.openecomp.sdc.onboarding.Constants.RESOURCES_CHANGED;
+import static org.openecomp.sdc.onboarding.Constants.RESOURCE_BUILD_DATA;
+import static org.openecomp.sdc.onboarding.Constants.SKIP_MAIN_SOURCE_COMPILE;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -24,64 +33,65 @@
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.util.Collection;
 import java.util.HashMap;
-import java.util.Iterator;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
 import java.util.function.BiFunction;
 import java.util.function.Function;
-import java.util.stream.Stream;
+import org.apache.maven.artifact.Artifact;
 import org.apache.maven.project.MavenProject;
 
 public class BuildState {
 
-    private static Map<String, Long> fullBuildData = new HashMap<>();
-    private static Map<String, Long> fullResourceBuildData = new HashMap<>();
+    private static Map<String, Map> compileDataStore = new HashMap<>();
     private static Map<String, Object> moduleBuildData = new HashMap<>();
     private static Map<String, Object> resourceBuildData = new HashMap<>();
+    private static Map<String, Artifact> artifacts = new HashMap<>();
+    private static Set<String> executeTestsIfDependsOnStore = new HashSet<>();
+    private static Set<String> pmdExecutedInRun = new HashSet<>();
 
-    private static File buildStateFile;
-    private static File resourceStateFile;
-    private File moduleBuildDataFile;
-    private File resourceBuildDataFile;
+    private static File compileStateFile;
     private MavenProject project;
-    private String buildStateFilePath;
-    private String resourceStateFilePath;
+    private String compileStateFilePath;
 
-    private void readFullBuildState() {
-        buildStateFile = initialize(this::getBuildStateFile, fullBuildData,
-                buildStateFilePath.substring(0, buildStateFilePath.indexOf('/')), project);
+    static {
+        initializeStore();
+        Optional<HashMap> masterStore = readState("compile.dat", HashMap.class);
+        compileDataStore = masterStore.isPresent() ? masterStore.get() : compileDataStore;
     }
 
-    private void readResourceBuildState() {
-        resourceStateFile = initialize(this::getResourceStateFile, fullResourceBuildData,
-                resourceStateFilePath.substring(0, resourceStateFilePath.indexOf('/')), project);
-
-    }
-
-    private File initialize(BiFunction<String, MavenProject, File> funct, Map store, String moduleCoordinate,
-            MavenProject proj) {
-        File file = funct.apply(moduleCoordinate, proj);
-        file.getParentFile().mkdirs();
-        try (FileInputStream fis = new FileInputStream(file); ObjectInputStream ois = new ObjectInputStream(fis);) {
-            if (store.isEmpty()) {
-                store.putAll(HashMap.class.cast(ois.readObject()));
+    void init() {
+        artifacts.clear();
+        for (Artifact artifact : project.getArtifacts()) {
+            if (artifact.isSnapshot() && JAR.equals(artifact.getType())) {
+                artifacts.put(artifact.getGroupId() + ":" + artifact.getArtifactId(), artifact);
             }
-        } catch (Exception e) {
-            store.clear();
         }
-        return file;
+        compileStateFile =
+                getCompileStateFile(compileStateFilePath.substring(0, compileStateFilePath.indexOf('/')), project);
     }
 
-    private void writeFullBuildState() throws IOException {
-        writeState(buildStateFile, fullBuildData);
+    static void initializeStore() {
+        compileDataStore.put(FULL_BUILD_DATA, new HashMap<>());
+        compileDataStore.put(FULL_RESOURCE_BUILD_DATA, new HashMap<>());
+        compileDataStore.put(MODULE_BUILD_DATA, new HashMap<>());
+        compileDataStore.put(RESOURCE_BUILD_DATA, new HashMap<>());
     }
 
-    private void writeFullResourceBuildState() throws IOException {
-        writeState(resourceStateFile, fullResourceBuildData);
+
+    static void recordPMDRun(String moduleCoordinates) {
+        pmdExecutedInRun.add(moduleCoordinates);
+    }
+
+    static boolean isPMDRun(String moduleCoordintes) {
+        return pmdExecutedInRun.contains(moduleCoordintes);
+    }
+
+    private void writeCompileState() throws IOException {
+        writeState(compileStateFile, compileDataStore);
     }
 
     private void writeState(File file, Map store) throws IOException {
@@ -90,20 +100,18 @@
         }
     }
 
-    private File getBuildStateFile(String moduleCoordinate, MavenProject proj) {
-        return getStateFile(moduleCoordinate, proj, buildStateFilePath);
+
+    private File getCompileStateFile(String moduleCoordinate, MavenProject proj) {
+        return getStateFile(moduleCoordinate, proj, compileStateFilePath);
     }
 
-    private File getResourceStateFile(String moduleCoordinate, MavenProject proj) {
-        return getStateFile(moduleCoordinate, proj, resourceStateFilePath);
-    }
 
     private File getStateFile(String moduleCoordinate, MavenProject proj, String filePath) {
         return new File(getTopParentProject(moduleCoordinate, proj).getBasedir(),
                 filePath.substring(filePath.indexOf('/') + 1));
     }
 
-    private MavenProject getTopParentProject(String moduleCoordinate, MavenProject proj) {
+    MavenProject getTopParentProject(String moduleCoordinate, MavenProject proj) {
         if (getModuleCoordinate(proj).equals(moduleCoordinate) || proj.getParent() == null) {
             return proj;
         } else {
@@ -116,10 +124,12 @@
     }
 
     void addModuleBuildTime(String moduleCoordinates, Long buildTime) {
-        Long lastTime = fullBuildData.put(moduleCoordinates, buildTime);
+        Long lastTime = Long.class.cast(compileDataStore.get(FULL_BUILD_DATA).put(moduleCoordinates, buildTime));
         try {
             if (lastTime == null || !lastTime.equals(buildTime)) {
-                writeFullBuildState();
+                if (!project.getProperties().containsKey(SKIP_MAIN_SOURCE_COMPILE)) {
+                    writeCompileState();
+                }
             }
         } catch (IOException ignored) {
             // ignored. No need to handle. System will take care.
@@ -127,10 +137,11 @@
     }
 
     void addResourceBuildTime(String moduleCoordinates, Long buildTime) {
-        if (project.getProperties().containsKey(RESOURCES_CHANGED)) {
-            Long lastTime = fullResourceBuildData.put(moduleCoordinates, buildTime);
+        if (project.getProperties().containsKey(RESOURCES_CHANGED)
+                    || compileDataStore.get(FULL_RESOURCE_BUILD_DATA).get(moduleCoordinates) == null) {
             try {
-                writeFullResourceBuildState();
+                compileDataStore.get(FULL_RESOURCE_BUILD_DATA).put(moduleCoordinates, buildTime);
+                writeCompileState();
             } catch (IOException ignored) {
                 // ignored. No need to handle. System will take care.
             }
@@ -142,15 +153,29 @@
     }
 
     Map<String, Object> readModuleBuildData() {
-        return readBuildData(moduleBuildDataFile);
+        return HashMap.class.cast(compileDataStore.get(MODULE_BUILD_DATA).get(getModuleCoordinate(project)));
     }
 
     void saveModuleBuildData(String moduleCoordinate) {
-        saveBuildData(moduleBuildDataFile, moduleBuildData.get(moduleCoordinate));
+        if (moduleBuildData.get(moduleCoordinate) != null) {
+            compileDataStore.get(MODULE_BUILD_DATA).put(moduleCoordinate, moduleBuildData.get(moduleCoordinate));
+        }
+        saveCompileData();
     }
 
     void saveResourceBuildData(String moduleCoordinate) {
-        saveBuildData(resourceBuildDataFile, resourceBuildData.get(moduleCoordinate));
+        if (resourceBuildData.get(moduleCoordinate) != null) {
+            compileDataStore.get(RESOURCE_BUILD_DATA).put(moduleCoordinate, resourceBuildData.get(moduleCoordinate));
+        }
+        saveCompileData();
+    }
+
+    void saveCompileData() {
+        saveBuildData(compileStateFile, compileDataStore);
+    }
+
+    void markTestsMandatoryModule(String moduleCoordinates) {
+        executeTestsIfDependsOnStore.add(moduleCoordinates);
     }
 
     private void saveBuildData(File file, Object dataToSave) {
@@ -166,41 +191,50 @@
     }
 
     Map<String, Object> readResourceBuildData() {
-        return readBuildData(resourceBuildDataFile);
+        return HashMap.class.cast(compileDataStore.get(RESOURCE_BUILD_DATA).get(getModuleCoordinate(project)));
     }
 
-    private Map<String, Object> readBuildData(File file) {
-        try (FileInputStream fis = new FileInputStream(file); ObjectInputStream ois = new ObjectInputStream(fis)) {
-            return HashMap.class.cast(ois.readObject());
-        } catch (Exception e) {
-            return new HashMap<>();
-        }
-    }
 
     void addResourceBuildData(String moduleCoordinates, Map currentModuleResourceBuildData) {
         resourceBuildData.put(moduleCoordinates, currentModuleResourceBuildData);
     }
 
     Long getBuildTime(String moduleCoordinates) {
-        if (fullBuildData.isEmpty()) {
-            readFullBuildState();
-            readResourceBuildState();
-        }
-        Long buildTime = fullBuildData.get(moduleCoordinates);
+        Long buildTime = Long.class.cast(compileDataStore.get(FULL_BUILD_DATA).get(moduleCoordinates));
         return buildTime == null ? 0 : buildTime;
     }
 
     Long getResourceBuildTime(String moduleCoordinates) {
-        Long resourceBuildTime = fullResourceBuildData.get(moduleCoordinates);
+        Long resourceBuildTime = Long.class.cast(compileDataStore.get(FULL_RESOURCE_BUILD_DATA).get(moduleCoordinates));
         return resourceBuildTime == null ? 0 : resourceBuildTime;
     }
 
     boolean isCompileMust(String moduleCoordinates, Collection<String> dependencies) {
+        for (String d : dependencies) {
+            if (artifacts.containsKey(d) && JAR.equals(artifacts.get(d).getType())) {
+                if (artifacts.get(d).getVersion().equals(project.getVersion()) && getBuildTime(d) == 0) {
+                    System.out.println(ANSI_YELLOW + "[WARNING:]" + "You have module[" + d
+                                               + "] not locally compiled even once, please compile your project once daily from root to have reliable build results."
+                                               + ANSI_COLOR_RESET);
+                    return true;
+                }
+            }
+        }
         return isMust(this::getBuildTime, moduleCoordinates, dependencies);
     }
 
-    boolean isTestMust(String moduleCoordinates, Collection<String> dependencies) {
-        return isMust(this::getResourceBuildTime, moduleCoordinates, dependencies);
+    boolean isTestExecutionMandatory() {
+        for (String d : artifacts.keySet()) {
+            if (executeTestsIfDependsOnStore.contains(d)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    boolean isTestMust(String moduleCoordinates) {
+        return getBuildTime(moduleCoordinates) > getResourceBuildTime(moduleCoordinates) || isMust(
+                this::getResourceBuildTime, moduleCoordinates, artifacts.keySet());
     }
 
     private boolean isMust(Function<String, Long> funct, String moduleCoordinates, Collection<String> dependencies) {
@@ -217,22 +251,4 @@
         return false;
     }
 
-    void markModuleDirty(File file) throws IOException {
-        if (file.exists()) {
-            Stream<String> lines = Files.lines(file.toPath());
-            Iterator<String> itr = lines.iterator();
-            while (itr.hasNext()) {
-                String line = itr.next();
-                Path path = Paths.get(line);
-                if (path.toFile().exists()) {
-                    if (path.toFile().setLastModified(System.currentTimeMillis())) {
-                        break;
-                    } else {
-                        continue;
-                    }
-                }
-            }
-        }
-    }
-
 }
diff --git a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/Constants.java b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/Constants.java
index 96abc47..c639c6d 100644
--- a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/Constants.java
+++ b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/Constants.java
@@ -2,14 +2,44 @@
 
 public class Constants {
 
+    private Constants() {
+    }
+
     public static final String JACOCO_SKIP = "jacoco.skip";
     public static final String FORK_COUNT = "fork.count";
+    public static final String FORK_MODE = "fork.mode";
+    public static final String SKIP_PMD = "skipPMD";
     public static final String JAVA_EXT = ".java";
-    public static final String CLASS_EXT = ".class";
+    public static final String ANY_EXT = "*";
     public static final String SKIP_TEST_RUN = "skipTestRun";
+    public static final String SKIP_TESTS = "skipTests";
     public static final String MAIN = "main";
     public static final String TEST = "test";
-    public static final String JAVA = "java";
     public static final String RESOURCES_CHANGED = "resourcesChanged";
     public static final String UNICORN = "unicorn";
+    public static final String ANSI_YELLOW = "\u001B[43m";
+    public static final String ANSI_COLOR_RESET = "\u001B[0m";
+    public static final String SKIP_MAIN_SOURCE_COMPILE = "skipMainSourceCompile";
+    public static final String SKIP_TEST_SOURCE_COMPILE = "skipTestSourceCompile";
+    public static final String MAIN_CHECKSUM = "mainChecksum";
+    public static final String TEST_CHECKSUM = "testChecksum";
+    public static final String RESOURCE_CHECKSUM = "resourceChecksum";
+    public static final String MAIN_SOURCE_CHECKSUM = "mainSourceChecksum";
+    public static final String TEST_SOURCE_CHECKSUM = "testSourceChecksum";
+    public static final String GENERATED_SOURCE_CHECKSUM = "generatedSourceChecksum";
+    public static final String EMPTY_JAR = "emptyJAR";
+    public static final String JAR = "jar";
+    public static final String SHA1 = "sha1";
+    public static final String COLON = ":";
+    public static final String DOT = ".";
+    public static final String FULL_BUILD_DATA = "fullBuildData";
+    public static final String FULL_RESOURCE_BUILD_DATA = "fullResourceBuildData";
+    public static final String MODULE_BUILD_DATA = "moduleBuildData";
+    public static final String RESOURCE_BUILD_DATA = "resourceBuildData";
+    public static final String RESOURCE_ONLY = "resourceOnly";
+    public static final String TEST_RESOURCE_ONLY = "testResourceOnly";
+    public static final String INSTRUMENT_WITH_TEST_ONLY = "instrumentWithTestOnly";
+    public static final String RESOURCE_WITH_TEST_ONLY = "resourceWithTestOnly";
+    public static final String INSTRUMENT_ONLY = "instrumentOnly";
+    public static final String TEST_ONLY = "testOnly";
 }
diff --git a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/InitializationHelperMojo.java b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/InitializationHelperMojo.java
index cbf6f69..8b0ff0e 100644
--- a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/InitializationHelperMojo.java
+++ b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/InitializationHelperMojo.java
@@ -17,7 +17,9 @@
 package org.openecomp.sdc.onboarding;
 
 import static org.openecomp.sdc.onboarding.Constants.FORK_COUNT;
+import static org.openecomp.sdc.onboarding.Constants.FORK_MODE;
 import static org.openecomp.sdc.onboarding.Constants.JACOCO_SKIP;
+import static org.openecomp.sdc.onboarding.Constants.SKIP_PMD;
 import static org.openecomp.sdc.onboarding.Constants.UNICORN;
 
 import org.apache.maven.plugin.AbstractMojo;
@@ -29,29 +31,39 @@
 import org.apache.maven.plugins.annotations.ResolutionScope;
 import org.apache.maven.project.MavenProject;
 
-@Mojo(name = "init-helper", threadSafe = true, defaultPhase = LifecyclePhase.PRE_CLEAN,
-        requiresDependencyResolution = ResolutionScope.NONE)
+@Mojo(name = "init-helper", threadSafe = true, defaultPhase = LifecyclePhase.GENERATE_RESOURCES,
+        requiresDependencyResolution = ResolutionScope.TEST)
 public class InitializationHelperMojo extends AbstractMojo {
 
     @Parameter(defaultValue = "${project}", readonly = true)
     private MavenProject project;
+    @Parameter
+    private BuildState buildState;
+    @Parameter
+    private String excludePackaging;
 
     public void execute() throws MojoExecutionException, MojoFailureException {
 
+        if (project.getPackaging().equals(excludePackaging)) {
+            return;
+        }
+        project.getProperties().setProperty("skipGet", "false");
         if (System.getProperties().containsKey(JACOCO_SKIP) && Boolean.FALSE.equals(Boolean.valueOf(
                 System.getProperties().getProperty(JACOCO_SKIP)))) {
             project.getProperties().setProperty(FORK_COUNT, "1");
+            project.getProperties().setProperty(FORK_MODE, "once");
         } else {
             project.getProperties().setProperty(FORK_COUNT, "0");
+            project.getProperties().setProperty(FORK_MODE, "never");
         }
 
-        if (System.getProperties().containsKey(UNICORN)) {
-            project.getProperties().setProperty("classes", "classes/**/*.class");
-            project.getProperties().setProperty("testClasses", "test-classes/**/*.class");
-            project.getProperties().setProperty("mavenStatus", "maven-status/**");
-            project.getProperties().setProperty("pmd", "pmd/**");
-            project.getProperties().setProperty("customGeneratedSources", "generated-sources/custom/**");
+        project.getProperties().setProperty(SKIP_PMD, Boolean.TRUE.toString());
 
+        if (System.getProperties().containsKey(UNICORN)) {
+            buildState.init();
+        } else {
+            project.getProperties().setProperty("skipMainSourceCompile", "false");
+            project.getProperties().setProperty("skipTestSourceCompile", "false");
         }
 
     }
diff --git a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PostCompileHelperMojo.java b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PostCompileHelperMojo.java
index 9ab3735..04e0ca8 100644
--- a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PostCompileHelperMojo.java
+++ b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PostCompileHelperMojo.java
@@ -16,26 +16,18 @@
 
 package org.openecomp.sdc.onboarding;
 
-import static org.openecomp.sdc.onboarding.Constants.CLASS_EXT;
-import static org.openecomp.sdc.onboarding.Constants.JAVA_EXT;
-import static org.openecomp.sdc.onboarding.Constants.MAIN;
-import static org.openecomp.sdc.onboarding.Constants.RESOURCES_CHANGED;
-import static org.openecomp.sdc.onboarding.Constants.SKIP_TEST_RUN;
+import static org.openecomp.sdc.onboarding.Constants.INSTRUMENT_ONLY;
+import static org.openecomp.sdc.onboarding.Constants.INSTRUMENT_WITH_TEST_ONLY;
+import static org.openecomp.sdc.onboarding.Constants.RESOURCE_ONLY;
+import static org.openecomp.sdc.onboarding.Constants.RESOURCE_WITH_TEST_ONLY;
+import static org.openecomp.sdc.onboarding.Constants.SKIP_MAIN_SOURCE_COMPILE;
+import static org.openecomp.sdc.onboarding.Constants.SKIP_PMD;
+import static org.openecomp.sdc.onboarding.Constants.SKIP_TEST_SOURCE_COMPILE;
+import static org.openecomp.sdc.onboarding.Constants.TEST_ONLY;
+import static org.openecomp.sdc.onboarding.Constants.TEST_RESOURCE_ONLY;
 import static org.openecomp.sdc.onboarding.Constants.UNICORN;
 
 import java.io.File;
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-import org.apache.maven.artifact.Artifact;
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugins.annotations.LifecyclePhase;
@@ -44,7 +36,7 @@
 import org.apache.maven.plugins.annotations.ResolutionScope;
 import org.apache.maven.project.MavenProject;
 
-@Mojo(name = "post-compile-helper", threadSafe = true, defaultPhase = LifecyclePhase.PROCESS_TEST_CLASSES,
+@Mojo(name = "post-compile-helper", threadSafe = true, defaultPhase = LifecyclePhase.TEST_COMPILE,
         requiresDependencyResolution = ResolutionScope.TEST)
 public class PostCompileHelperMojo extends AbstractMojo {
 
@@ -53,89 +45,15 @@
     @Parameter(defaultValue = "${project.artifact.groupId}:${project.artifact.artifactId}")
     private String moduleCoordinates;
     @Parameter
-    private Long staleThreshold;
-    @Parameter
     private String excludePackaging;
     @Parameter
-    private List<String> excludeDependencies;
-    @Parameter
-    private File mainSourceLocation;
-    @Parameter
-    private File testSourceLocation;
-    @Parameter
-    private File mainCompiledLocation;
-    @Parameter
-    private File testCompiledLocation;
-    @Parameter
-    private File inputSourceFilesList;
-    @Parameter
-    private File inputTestFilesList;
-    @Parameter
     private BuildState buildState;
     @Parameter
     private File mainResourceLocation;
     @Parameter
     private File testResourceLocation;
-    @Parameter
-    private File compiledTestFilesList;
 
 
-    private File[] getCompiledClasses(File compiledFiles) {
-        if (!compiledFiles.exists()) {
-            return new File[0];
-        }
-        File[] list = null;
-        try {
-            list = Files.walk(Paths.get(compiledFiles.getAbsolutePath()))
-                        .filter(p -> p.toFile().getAbsolutePath().endsWith(CLASS_EXT)).map(p -> p.toFile())
-                        .sorted(this::compare).collect(Collectors.toList()).toArray(new File[0]);
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-        if (list == null || list.length == 0) {
-            return new File[0];
-        }
-        return list;
-    }
-
-    private int compare(File file1, File file2) {
-        if (file1.lastModified() > file2.lastModified()) {
-            return 1;
-        }
-        if (file1.lastModified() < file2.lastModified()) {
-            return -1;
-        }
-        return 0;
-    }
-
-    private File[] getStaleCompiledClasses(File[] compiledClasses, File javaSourceLocation) {
-        List<File> staleFiles = new ArrayList<>();
-        for (File file : compiledClasses) {
-            String classLocation = file.getAbsolutePath().replace(
-                    project.getBasedir().getAbsolutePath() + File.separator + "target" + File.separator, "");
-            String classLocationWithPackageOnly =
-                    classLocation.substring(classLocation.indexOf(File.separatorChar) + 1);
-            String sourceFilePath = javaSourceLocation.getAbsolutePath() + File.separator + classLocationWithPackageOnly
-                                                                                                    .replace(CLASS_EXT,
-                                                                                                            JAVA_EXT);
-            if (Paths.get(sourceFilePath).toFile().exists()) {
-                return staleFiles.toArray(new File[0]);
-            } else {
-                staleFiles.add(file);
-            }
-        }
-        return staleFiles.toArray(new File[0]);
-    }
-
-    private boolean deleteAll(File[] files) {
-        for (File file : files) {
-            if (!file.delete()) {
-                return false;
-            }
-        }
-        return true;
-    }
-
     public void execute() throws MojoExecutionException {
         if (!System.getProperties().containsKey(UNICORN)) {
             return;
@@ -143,93 +61,40 @@
         if (project.getPackaging().equals(excludePackaging)) {
             return;
         }
-        String moduleLocation = project.getBasedir().getAbsolutePath();
-
-        File[] mainClasses = getCompiledClasses(mainCompiledLocation);
-        processStaleClassesIfAny(mainClasses, mainSourceLocation, inputSourceFilesList);
-
-        File[] testClasses = getCompiledClasses(testCompiledLocation);
-        processStaleClassesIfAny(testClasses, testSourceLocation, inputTestFilesList);
-
-        if (mainClasses.length == 0 && testClasses.length == 0) {
-            return;
+        if (project.getProperties().containsKey(TEST_ONLY)) {
+            project.getProperties().setProperty(SKIP_MAIN_SOURCE_COMPILE, Boolean.TRUE.toString());
+            project.getProperties().remove(TEST_ONLY);
         }
-        buildState.addModuleBuildTime(project.getGroupId() + ":" + project.getArtifactId(),
-                mainClasses.length > 0 ? mainClasses[mainClasses.length - 1].lastModified() :
-                        testClasses.length > 0 ? testClasses[testClasses.length - 1].lastModified() : 0);
+        if (project.getProperties().containsKey(INSTRUMENT_ONLY)) {
+            project.getProperties().setProperty(SKIP_MAIN_SOURCE_COMPILE, Boolean.TRUE.toString());
+            project.getProperties().setProperty(SKIP_TEST_SOURCE_COMPILE, Boolean.TRUE.toString());
+            project.getProperties().remove(INSTRUMENT_ONLY);
+        }
+        if (project.getProperties().containsKey(INSTRUMENT_WITH_TEST_ONLY)) {
+            project.getProperties().setProperty(SKIP_MAIN_SOURCE_COMPILE, Boolean.TRUE.toString());
+            project.getProperties().remove(INSTRUMENT_WITH_TEST_ONLY);
+        }
+        if (project.getProperties().containsKey(RESOURCE_WITH_TEST_ONLY)) {
+            project.getProperties().setProperty(SKIP_MAIN_SOURCE_COMPILE, Boolean.TRUE.toString());
+            project.getProperties().remove(RESOURCE_WITH_TEST_ONLY);
+        }
+        if (project.getProperties().containsKey(RESOURCE_ONLY)) {
+            project.getProperties().setProperty(SKIP_MAIN_SOURCE_COMPILE, Boolean.TRUE.toString());
+            project.getProperties().setProperty(SKIP_TEST_SOURCE_COMPILE, Boolean.TRUE.toString());
+            project.getProperties().remove(RESOURCE_ONLY);
+        }
+        if (project.getProperties().containsKey(TEST_RESOURCE_ONLY)) {
+            project.getProperties().setProperty(SKIP_MAIN_SOURCE_COMPILE, Boolean.TRUE.toString());
+            project.getProperties().setProperty(SKIP_TEST_SOURCE_COMPILE, Boolean.TRUE.toString());
+            project.getProperties().remove(TEST_RESOURCE_ONLY);
+        }
+        if (!project.getProperties().containsKey(SKIP_MAIN_SOURCE_COMPILE)) {
+            buildState.addModuleBuildTime(moduleCoordinates, System.currentTimeMillis());
+            project.getProperties().setProperty(SKIP_PMD, Boolean.FALSE.toString());
+        }
+        if (!project.getProperties().containsKey(SKIP_TEST_SOURCE_COMPILE)) {
+            project.getProperties().setProperty(SKIP_PMD, Boolean.FALSE.toString());
+        }
         buildState.saveModuleBuildData(moduleCoordinates);
-        Map<String, Object> resourceBuildData = getCurrentResourceBuildData();
-        Map<String, Object> lastTimeResourceBuildData = buildState.readResourceBuildData();
-        boolean resourceDataSame = resourceBuildData.equals(lastTimeResourceBuildData);
-        if (!resourceDataSame) {
-            buildState.addResourceBuildData(moduleCoordinates, resourceBuildData);
-            project.getProperties().setProperty(SKIP_TEST_RUN, Boolean.FALSE.toString());
-        }
-        boolean resourceMainBuildDataSameWithPreviousBuild =
-                lastTimeResourceBuildData.get(MAIN) != null && resourceBuildData.get(MAIN)
-                                                                                .equals(lastTimeResourceBuildData
-                                                                                                .get(MAIN));
-        if (!resourceMainBuildDataSameWithPreviousBuild) {
-            project.getProperties().setProperty(RESOURCES_CHANGED, Boolean.TRUE.toString());
-        }
-        if (!project.getProperties().containsKey(SKIP_TEST_RUN)) {
-            if (compiledTestFilesList.exists()
-                        && compiledTestFilesList.lastModified() > System.currentTimeMillis() - staleThreshold) {
-                project.getProperties().setProperty(SKIP_TEST_RUN, Boolean.FALSE.toString());
-            }
-        }
-    }
-
-    private void processStaleClassesIfAny(File[] classes, File sourceLocation, File listFile)
-            throws MojoExecutionException {
-        if (classes.length > 0) {
-            List<File> list = new ArrayList<>(Arrays.asList(classes));
-            File[] staleClasses = null;
-            boolean allStale = listFile.isFile() && listFile.length() == 0;
-            if (allStale) {
-                staleClasses = classes;
-                listFile.delete();
-            } else {
-                list.removeIf(f -> f.lastModified() > classes[classes.length - 1].lastModified() - staleThreshold);
-                staleClasses = getStaleCompiledClasses(list.toArray(new File[0]), sourceLocation);
-            }
-            if (!deleteAll(staleClasses)) {
-                throw new MojoExecutionException(
-                        "****** Please remove 'target' directory manually under path " + project.getBasedir()
-                                                                                                .getAbsolutePath());
-            }
-        }
-    }
-
-    private Map<String, Object> getCurrentResourceBuildData() {
-        HashMap<String, Object> resourceBuildStateData = new HashMap<>();
-        try {
-            resourceBuildStateData.put("main", readResources(mainResourceLocation));
-            resourceBuildStateData.put("test", readResources(testResourceLocation));
-            resourceBuildStateData.put("dependency", getDependencies());
-        } catch (IOException ioException) {
-            throw new UncheckedIOException(ioException);
-        }
-        return resourceBuildStateData;
-    }
-
-    private Map<String, Long> readResources(File file) throws IOException {
-        Map<String, Long> resources = new HashMap<>();
-        if (file.exists()) {
-            List<Path> list = Files.walk(Paths.get(file.getAbsolutePath())).filter(Files::isRegularFile)
-                                   .collect(Collectors.toList());
-            for (Path path : list) {
-                resources.put(path.toFile().getAbsolutePath(), path.toFile().lastModified());
-            }
-        }
-        return resources;
-    }
-
-    private Map<String, String> getDependencies() {
-        Map<String, String> dependencies = new HashMap<>();
-        for (Artifact d : project.getArtifacts()) {
-            dependencies.put(d.getGroupId() + ":" + d.getArtifactId(), d.getVersion());
-        }
-        return dependencies;
     }
 }
diff --git a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PostSourceGeneratorMojo.java b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PostSourceGeneratorMojo.java
new file mode 100644
index 0000000..36e5f8a
--- /dev/null
+++ b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PostSourceGeneratorMojo.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright © 2018 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on a "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openecomp.sdc.onboarding;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.ResolutionScope;
+
+
+@Mojo(name = "post-source-generator-helper", threadSafe = true, defaultPhase = LifecyclePhase.GENERATE_RESOURCES,
+        requiresDependencyResolution = ResolutionScope.TEST)
+public class PostSourceGeneratorMojo extends PreCompileHelperMojo {
+
+    public void execute() throws MojoExecutionException, MojoFailureException {
+        if (isCodeGenerator()) {
+            super.execute();
+        }
+    }
+
+    //    @Override
+    void deleteAllClasses(File file) {
+        if (!file.exists()) {
+            return;
+        }
+        try {
+            List<File> list =
+                    Files.walk(Paths.get(file.getAbsolutePath())).filter(Files::isRegularFile).map(p -> p.toFile())
+                         .collect(Collectors.toList());
+            for (File f : list) {
+                f.delete();
+            }
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+
+    }
+}
diff --git a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PostTestRunHelperMojo.java b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PostTestRunHelperMojo.java
index 5b326f3..c2816db 100644
--- a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PostTestRunHelperMojo.java
+++ b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PostTestRunHelperMojo.java
@@ -16,6 +16,7 @@
 
 package org.openecomp.sdc.onboarding;
 
+import static org.openecomp.sdc.onboarding.Constants.SKIP_TESTS;
 import static org.openecomp.sdc.onboarding.Constants.SKIP_TEST_RUN;
 import static org.openecomp.sdc.onboarding.Constants.UNICORN;
 
@@ -49,11 +50,13 @@
         if (project.getPackaging().equals(excludePackaging)) {
             return;
         }
-        buildState.saveResourceBuildData(moduleCoordinates);
+
         if (project.getProperties().containsKey(SKIP_TEST_RUN) && !Boolean.valueOf(
                 project.getProperties().getProperty(SKIP_TEST_RUN))) {
-            if (!System.getProperties().containsKey("skipTests")) {
+            if (!System.getProperties().containsKey(SKIP_TESTS)) {
+                buildState.saveResourceBuildData(moduleCoordinates);
                 buildState.addResourceBuildTime(moduleCoordinates, System.currentTimeMillis());
+
             }
         }
 
diff --git a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PreCompileHelperMojo.java b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PreCompileHelperMojo.java
index faa3167..854ef7f 100644
--- a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PreCompileHelperMojo.java
+++ b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PreCompileHelperMojo.java
@@ -16,127 +16,417 @@
 
 package org.openecomp.sdc.onboarding;
 
+import static org.openecomp.sdc.onboarding.BuildHelper.getArtifactPathInLocalRepo;
+import static org.openecomp.sdc.onboarding.BuildHelper.getChecksum;
+import static org.openecomp.sdc.onboarding.BuildHelper.getSourceChecksum;
+import static org.openecomp.sdc.onboarding.BuildHelper.readState;
+import static org.openecomp.sdc.onboarding.Constants.ANY_EXT;
+import static org.openecomp.sdc.onboarding.Constants.COLON;
+import static org.openecomp.sdc.onboarding.Constants.DOT;
+import static org.openecomp.sdc.onboarding.Constants.EMPTY_JAR;
+import static org.openecomp.sdc.onboarding.Constants.GENERATED_SOURCE_CHECKSUM;
+import static org.openecomp.sdc.onboarding.Constants.INSTRUMENT_ONLY;
+import static org.openecomp.sdc.onboarding.Constants.INSTRUMENT_WITH_TEST_ONLY;
+import static org.openecomp.sdc.onboarding.Constants.JAR;
+import static org.openecomp.sdc.onboarding.Constants.JAVA_EXT;
 import static org.openecomp.sdc.onboarding.Constants.MAIN;
+import static org.openecomp.sdc.onboarding.Constants.MAIN_CHECKSUM;
+import static org.openecomp.sdc.onboarding.Constants.MAIN_SOURCE_CHECKSUM;
+import static org.openecomp.sdc.onboarding.Constants.RESOURCES_CHANGED;
+import static org.openecomp.sdc.onboarding.Constants.RESOURCE_CHECKSUM;
+import static org.openecomp.sdc.onboarding.Constants.RESOURCE_ONLY;
+import static org.openecomp.sdc.onboarding.Constants.RESOURCE_WITH_TEST_ONLY;
+import static org.openecomp.sdc.onboarding.Constants.SHA1;
+import static org.openecomp.sdc.onboarding.Constants.SKIP_MAIN_SOURCE_COMPILE;
+import static org.openecomp.sdc.onboarding.Constants.SKIP_PMD;
 import static org.openecomp.sdc.onboarding.Constants.SKIP_TEST_RUN;
+import static org.openecomp.sdc.onboarding.Constants.SKIP_TEST_SOURCE_COMPILE;
 import static org.openecomp.sdc.onboarding.Constants.TEST;
+import static org.openecomp.sdc.onboarding.Constants.TEST_CHECKSUM;
+import static org.openecomp.sdc.onboarding.Constants.TEST_ONLY;
+import static org.openecomp.sdc.onboarding.Constants.TEST_RESOURCE_ONLY;
+import static org.openecomp.sdc.onboarding.Constants.TEST_SOURCE_CHECKSUM;
 import static org.openecomp.sdc.onboarding.Constants.UNICORN;
 
 import java.io.File;
 import java.io.IOException;
 import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
 import org.apache.maven.artifact.Artifact;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.model.Plugin;
+import org.apache.maven.model.PluginExecution;
 import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.InvalidPluginDescriptorException;
+import org.apache.maven.plugin.MavenPluginManager;
 import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugin.MojoNotFoundException;
+import org.apache.maven.plugin.PluginDescriptorParsingException;
+import org.apache.maven.plugin.PluginResolutionException;
+import org.apache.maven.plugin.descriptor.MojoDescriptor;
+import org.apache.maven.plugins.annotations.Component;
 import org.apache.maven.plugins.annotations.LifecyclePhase;
 import org.apache.maven.plugins.annotations.Mojo;
 import org.apache.maven.plugins.annotations.Parameter;
 import org.apache.maven.plugins.annotations.ResolutionScope;
 import org.apache.maven.project.MavenProject;
 
-@Mojo(name = "pre-compile-helper", threadSafe = true, defaultPhase = LifecyclePhase.GENERATE_SOURCES,
+
+@Mojo(name = "pre-compile-helper", threadSafe = true, defaultPhase = LifecyclePhase.GENERATE_RESOURCES,
         requiresDependencyResolution = ResolutionScope.TEST)
 public class PreCompileHelperMojo extends AbstractMojo {
 
-    @Parameter(defaultValue = "${project}", readonly = true)
+    @Parameter(defaultValue = "${project}")
     private MavenProject project;
     @Parameter(defaultValue = "${project.artifact.groupId}:${project.artifact.artifactId}")
     private String moduleCoordinates;
+    @Parameter(defaultValue = "${session}")
+    private MavenSession session;
     @Parameter
     private String excludePackaging;
     @Parameter
     private List<String> excludeDependencies;
     @Parameter
-    private File mainCompiledLocation;
-    @Parameter
-    private File testCompiledLocation;
-    @Parameter
-    private File inputSourceFilesList;
-    @Parameter
-    private File inputTestFilesList;
-    @Parameter
     private BuildState buildState;
+    @Parameter
+    private File mainSourceLocation;
+    @Parameter
+    private File testSourceLocation;
+    @Parameter
+    private File generatedSourceLocation;
+    @Component
+    private MavenPluginManager pluginManager;
+    @Parameter
+    private File mainResourceLocation;
+    @Parameter
+    private File testResourceLocation;
+    private Map<String, Object> resourceBuildData;
 
-    public void execute() throws MojoExecutionException {
-        if (!System.getProperties().containsKey(UNICORN)) {
-            return;
-        }
+    private static Map<String, String> checksumMap;
+
+    static {
+        checksumMap = readCurrentPMDState("pmd.dat");
+    }
+
+    public void execute() throws MojoExecutionException, MojoFailureException {
+
+        long mainChecksum = 0, testChecksum = 0, resourceChecksum = 0;
+        Optional<String> artifactPath;
+
         if (project.getPackaging().equals(excludePackaging)) {
             return;
         }
+        init();
+        project.getProperties()
+               .setProperty(MAIN_CHECKSUM, String.valueOf(mainChecksum = getChecksum(mainSourceLocation, JAVA_EXT)));
+        project.getProperties()
+               .setProperty(TEST_CHECKSUM, String.valueOf(testChecksum = getChecksum(testSourceLocation, JAVA_EXT)));
+        String checksum = mainChecksum + COLON + testChecksum;
+        if (!checksum.equals(checksumMap.get(moduleCoordinates)) || isPMDMandatory(project.getArtifacts())) {
+            project.getProperties().setProperty(SKIP_PMD, Boolean.FALSE.toString());
+            buildState.recordPMDRun(moduleCoordinates);
+        }
+        project.getProperties().setProperty(EMPTY_JAR, "");
+        if (!System.getProperties().containsKey(UNICORN)) {
+            return;
+        }
+
+        project.getProperties().setProperty(RESOURCE_CHECKSUM,
+                String.valueOf(resourceChecksum = getChecksum(mainResourceLocation, ANY_EXT)));
+        byte[] sourceChecksum = calculateChecksum(mainChecksum, resourceChecksum).getBytes();
+        boolean instrumented = isCurrentModuleInstrumented();
+        artifactPath = getArtifactPathInLocalRepo(session.getLocalRepository().getUrl(), project, sourceChecksum);
+
+        boolean isFirstBuild = buildState.getBuildTime(moduleCoordinates) == 0 || !artifactPath.isPresent();
 
         Map<String, Object> moduleBuildData = getCurrentModuleBuildData();
         Map<String, Object> lastTimeModuleBuildData = buildState.readModuleBuildData();
+        resourceBuildData = getCurrentResourceBuildData();
+        Map<String, Object> lastTimeResourceBuildData = buildState.readResourceBuildData();
 
-        boolean buildDataSameWithPreviousBuild = lastTimeModuleBuildData.get(MAIN) != null && moduleBuildData.get(MAIN)
-                                                                                                             .equals(lastTimeModuleBuildData
-                                                                                                                             .get(MAIN));
-        boolean isFirstBuild = buildState.getBuildTime(moduleCoordinates) == 0;
+        boolean buildDataSameWithPreviousBuild =
+                isBuildDataSameWithPreviousBuild(lastTimeModuleBuildData, moduleBuildData);
+        boolean resourceMainBuildDataSameWithPreviousBuild =
+                isResourceMainBuildDataSameWithPreviousBuild(lastTimeResourceBuildData);
 
-        if (isCompileNeeded(HashMap.class.cast(moduleBuildData.get(MAIN)).keySet(), isFirstBuild,
-                buildDataSameWithPreviousBuild)) {
-            try {
-                buildState.markModuleDirty(inputSourceFilesList);
-                buildState.markModuleDirty(inputTestFilesList);
-                project.getProperties().setProperty(SKIP_TEST_RUN, "false");
-            } catch (IOException e) {
-                throw new UncheckedIOException(e);
-            }
-        }
+        boolean mainToBeCompiled = isCompileNeeded(HashMap.class.cast(moduleBuildData.get(MAIN)).keySet(), isFirstBuild,
+                buildDataSameWithPreviousBuild);
 
-        if (!moduleBuildData.get(TEST).equals(lastTimeModuleBuildData.get(TEST))) {
-            try {
-                buildState.markModuleDirty(inputTestFilesList);
-                project.getProperties().setProperty(SKIP_TEST_RUN, Boolean.FALSE.toString());
-            } catch (IOException e) {
-                throw new UncheckedIOException(e);
-            }
-        }
+        boolean resourceDataSame = resourceBuildData.equals(lastTimeResourceBuildData);
 
-        if (!moduleBuildData.equals(lastTimeModuleBuildData)) {
+        boolean testToBeCompiled =
+                lastTimeModuleBuildData == null || !moduleBuildData.get(TEST).equals(lastTimeModuleBuildData.get(TEST));
+        setMainBuildAttribute(mainToBeCompiled, testToBeCompiled);
+        generateSignature(sourceChecksum);
+        setTestBuild(resourceDataSame, resourceMainBuildDataSameWithPreviousBuild, testToBeCompiled, mainToBeCompiled);
+        setInstrumentedBuild(testToBeCompiled, mainToBeCompiled, instrumented);
+
+        if (!moduleBuildData.equals(lastTimeModuleBuildData) || isFirstBuild) {
             buildState.addModuleBuildData(moduleCoordinates, moduleBuildData);
         }
+        setResourceBuild(resourceMainBuildDataSameWithPreviousBuild, mainToBeCompiled, testToBeCompiled);
+        setJarFlags(mainToBeCompiled, instrumented, !resourceMainBuildDataSameWithPreviousBuild);
+        setInstallFlags(mainToBeCompiled, instrumented, project.getPackaging(),
+                !resourceMainBuildDataSameWithPreviousBuild);
 
-        if (inputSourceFilesList.isFile() && inputSourceFilesList.length() == 0) {
-            if (!inputSourceFilesList.delete()) {
-                throw new MojoExecutionException(
-                        "****** Please remove 'target' directory manually under path " + project.getBasedir()
-                                                                                                .getAbsolutePath());
-            }
+        if (!mainToBeCompiled && !instrumented && JAR.equals(project.getPackaging())
+                    && resourceMainBuildDataSameWithPreviousBuild) {
+            project.getProperties().setProperty("artifactPathToCopy", artifactPath.orElse(null));
         }
-        if (inputTestFilesList.isFile() && inputTestFilesList.length() == 0) {
-            if (!inputTestFilesList.delete()) {
-                throw new MojoExecutionException(
-                        "****** Please remove 'target' directory manually under path " + project.getBasedir()
-                                                                                                .getAbsolutePath());
+    }
+
+    private void generateSignature(byte[] sourceChecksum) {
+        try {
+            Files.write(Paths.get(project.getBuild().getDirectory(), project.getBuild().getFinalName() + DOT + UNICORN),
+                    sourceChecksum, StandardOpenOption.CREATE);
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
+    private String calculateChecksum(long mainChecksum, long resourceChecksum) throws MojoExecutionException {
+        try {
+            return getSourceChecksum(mainChecksum + COLON + resourceChecksum, SHA1);
+        } catch (NoSuchAlgorithmException e) {
+            throw new MojoExecutionException(e.getMessage(), e);
+        }
+    }
+
+    private boolean isResourceMainBuildDataSameWithPreviousBuild(Map<String, Object> lastTimeResourceBuildData) {
+        return lastTimeResourceBuildData != null && (lastTimeResourceBuildData.get(MAIN) != null && resourceBuildData
+                                                                                                            .get(MAIN)
+                                                                                                            .equals(lastTimeResourceBuildData
+                                                                                                                            .get(MAIN)));
+    }
+
+    private boolean isBuildDataSameWithPreviousBuild(Map<String, Object> lastTimeModuleBuildData,
+            Map<String, Object> moduleBuildData) {
+        return lastTimeModuleBuildData != null && (lastTimeModuleBuildData.get(MAIN) != null && moduleBuildData
+                                                                                                        .get(MAIN)
+                                                                                                        .equals(lastTimeModuleBuildData
+                                                                                                                        .get(MAIN)));
+    }
+
+    private void setInstrumentedBuild(boolean testToBeCompiled, boolean mainToBeCompiled, boolean instrumented) {
+        if (!testToBeCompiled && !mainToBeCompiled && instrumented) {
+            project.getProperties().setProperty(INSTRUMENT_ONLY, Boolean.TRUE.toString());
+            project.getProperties().remove(SKIP_MAIN_SOURCE_COMPILE);
+            project.getProperties().remove(SKIP_TEST_SOURCE_COMPILE);
+        }
+        if (testToBeCompiled && !mainToBeCompiled && instrumented) {
+            project.getProperties().setProperty(INSTRUMENT_WITH_TEST_ONLY, Boolean.TRUE.toString());
+            project.getProperties().remove(SKIP_MAIN_SOURCE_COMPILE);
+        }
+        if (instrumented) {
+            buildState.markTestsMandatoryModule(moduleCoordinates);
+            project.getProperties().setProperty(SKIP_TEST_RUN, Boolean.FALSE.toString());
+        }
+    }
+
+    private void setResourceBuild(boolean resourceMainBuildDataSameWithPreviousBuild, boolean mainToBeCompiled,
+            boolean testToBeCompiled) {
+        if (resourceMainBuildDataSameWithPreviousBuild) {
+            project.getProperties().setProperty("skipResourceCollection", Boolean.TRUE.toString());
+        } else {
+            project.getProperties().setProperty(RESOURCES_CHANGED, Boolean.TRUE.toString());
+        }
+        if (!resourceMainBuildDataSameWithPreviousBuild && !mainToBeCompiled) {
+            project.getProperties().remove(SKIP_MAIN_SOURCE_COMPILE);
+            if (!testToBeCompiled) {
+                project.getProperties().remove(SKIP_TEST_SOURCE_COMPILE);
+                project.getProperties().setProperty(RESOURCE_ONLY, Boolean.TRUE.toString());
+            } else {
+                project.getProperties().setProperty(RESOURCE_WITH_TEST_ONLY, Boolean.TRUE.toString());
             }
         }
     }
 
+    private void setTestBuild(boolean resourceDataSame, boolean resourceMainBuildDataSameWithPreviousBuild,
+            boolean testToBeCompiled, boolean mainToBeCompiled) {
+        if (!resourceDataSame) {
+            buildState.addResourceBuildData(moduleCoordinates, resourceBuildData);
+            project.getProperties().setProperty(SKIP_TEST_RUN, Boolean.FALSE.toString());
+            if (resourceMainBuildDataSameWithPreviousBuild && !testToBeCompiled && !mainToBeCompiled) {
+                project.getProperties().setProperty(TEST_RESOURCE_ONLY, Boolean.TRUE.toString());
+                project.getProperties().remove(SKIP_MAIN_SOURCE_COMPILE);
+                project.getProperties().remove(SKIP_TEST_SOURCE_COMPILE);
+            }
+        }
+    }
+
+    private void setMainBuildAttribute(boolean mainToBeCompiled, boolean testToBeCompiled) {
+        if (!mainToBeCompiled) {
+            project.getProperties().setProperty(SKIP_MAIN_SOURCE_COMPILE, Boolean.TRUE.toString());
+        }
+        if (testToBeCompiled && !mainToBeCompiled) {
+            project.getProperties().setProperty(TEST_ONLY, Boolean.TRUE.toString());
+            project.getProperties().remove(SKIP_MAIN_SOURCE_COMPILE);
+        }
+
+        if (mainToBeCompiled || testToBeCompiled) {
+            project.getProperties().setProperty(SKIP_TEST_RUN, Boolean.FALSE.toString());
+        } else {
+            project.getProperties().setProperty(SKIP_TEST_SOURCE_COMPILE, Boolean.TRUE.toString());
+        }
+    }
+
+    private void setJarFlags(boolean compile, boolean instrumented, boolean resourceChanged) {
+        if (compile || instrumented || resourceChanged) {
+            project.getProperties().setProperty(EMPTY_JAR, "");
+        } else {
+            project.getProperties().setProperty(EMPTY_JAR, "**/*");
+            project.getProperties().setProperty("mvnDsc", "false");
+        }
+    }
+
+    private void setInstallFlags(boolean compile, boolean instrumented, String packaging, boolean resourceChanged) {
+        if (!compile && !instrumented && !resourceChanged && JAR.equals(packaging)) {
+            project.getProperties().setProperty("skipInstall", Boolean.TRUE.toString());
+        }
+    }
+
     private boolean isCompileNeeded(Collection<String> dependencyCoordinates, boolean isFirstBuild,
-            boolean buildDataSame) {
+            boolean buildDataSame) throws MojoFailureException {
         return isFirstBuild || !buildDataSame || buildState.isCompileMust(moduleCoordinates, dependencyCoordinates);
     }
 
+    private boolean isCurrentModuleInstrumented() {
+        try {
+            return scanModuleFor(LifecyclePhase.PROCESS_CLASSES.id(), LifecyclePhase.PROCESS_TEST_CLASSES.id(),
+                    LifecyclePhase.COMPILE.id(), LifecyclePhase.TEST_COMPILE.id());
+        } catch (Exception e) {
+            return true;
+        }
+    }
+
+    boolean isCodeGenerator() {
+        try {
+            return scanModuleFor(LifecyclePhase.GENERATE_RESOURCES.id(), LifecyclePhase.GENERATE_SOURCES.id(),
+                    LifecyclePhase.GENERATE_TEST_RESOURCES.id(), LifecyclePhase.GENERATE_TEST_SOURCES.id());
+        } catch (Exception e) {
+            return true;
+        }
+    }
+
     private Map<String, Object> getCurrentModuleBuildData() {
         Map<String, Object> moduleBuildData = new HashMap<>();
         moduleBuildData.put(MAIN, new HashMap<String, String>());
         moduleBuildData.put(TEST, new HashMap<String, String>());
+        HashMap.class.cast(moduleBuildData.get(MAIN))
+                     .put(MAIN_SOURCE_CHECKSUM, project.getProperties().getProperty(MAIN_CHECKSUM));
+        HashMap.class.cast(moduleBuildData.get(TEST))
+                     .put(TEST_SOURCE_CHECKSUM, project.getProperties().getProperty(TEST_CHECKSUM));
+        if (isCodeGenerator()) {
+            HashMap.class.cast(moduleBuildData.get(MAIN))
+                         .put(GENERATED_SOURCE_CHECKSUM, getChecksum(generatedSourceLocation, JAVA_EXT));
+        }
         if (project.getArtifacts() == null || project.getArtifacts().isEmpty()) {
             return moduleBuildData;
         }
         for (Artifact dependency : project.getArtifacts()) {
+            String fileNme = dependency.getFile().getName();
             if (excludeDependencies.contains(dependency.getScope())) {
                 HashMap.class.cast(moduleBuildData.get(TEST))
-                             .put(dependency.getGroupId() + ":" + dependency.getArtifactId(), dependency.getVersion());
+                             .put(dependency.getGroupId() + COLON + dependency.getArtifactId(),
+                                     fileNme.endsWith(dependency.getVersion() + DOT + JAR) ? dependency.getVersion() :
+                                             fileNme);
                 continue;
             }
             HashMap.class.cast(moduleBuildData.get(MAIN))
-                         .put(dependency.getGroupId() + ":" + dependency.getArtifactId(), dependency.getVersion());
+                         .put(dependency.getGroupId() + COLON + dependency.getArtifactId(),
+                                 fileNme.endsWith(dependency.getVersion() + DOT + JAR) ? dependency.getVersion() :
+                                         fileNme);
         }
         return moduleBuildData;
     }
+
+    private static Map<String, String> readCurrentPMDState(String fileName) {
+        Optional<HashMap> val = readState(fileName, HashMap.class);
+        return val.orElseGet(HashMap::new);
+    }
+
+    private boolean isPMDMandatory(Set<Artifact> dependencies) {
+        for (Artifact artifact : dependencies) {
+            if (buildState.isPMDRun(artifact.getGroupId() + COLON + artifact.getArtifactId())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean scanModuleFor(String... types)
+            throws InvalidPluginDescriptorException, PluginResolutionException, MojoNotFoundException,
+                           PluginDescriptorParsingException {
+        for (Plugin plugin : project.getBuildPlugins()) {
+            if (!(plugin.getGroupId().equals("org.apache.maven.plugins") && plugin.getArtifactId().startsWith("maven"))
+                        && !plugin.getGroupId().startsWith("org.openecomp.sdc")) {
+                if (scanPlugin(plugin, types)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private boolean scanPlugin(Plugin plugin, String... types)
+            throws InvalidPluginDescriptorException, PluginDescriptorParsingException, MojoNotFoundException,
+                           PluginResolutionException {
+        for (PluginExecution pluginExecution : plugin.getExecutions()) {
+            if (pluginExecution.getPhase() != null) {
+                if (Arrays.asList(types).contains(pluginExecution.getPhase())) {
+                    return true;
+                }
+            }
+            for (String goal : pluginExecution.getGoals()) {
+                MojoDescriptor md = pluginManager.getMojoDescriptor(plugin, goal, project.getRemotePluginRepositories(),
+                        session.getRepositorySession());
+                if (Arrays.asList(types).contains(md.getPhase())) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private Map<String, Object> getCurrentResourceBuildData() {
+        HashMap<String, Object> resourceBuildStateData = new HashMap<>();
+        resourceBuildStateData.put(MAIN, project.getProperties().getProperty(RESOURCE_CHECKSUM));
+        resourceBuildStateData.put(TEST, getChecksum(testResourceLocation, ANY_EXT));
+        resourceBuildStateData.put("dependency", getDependencies().hashCode());
+        return resourceBuildStateData;
+    }
+
+    private Map<String, String> getDependencies() {
+        Map<String, String> dependencies = new HashMap<>();
+        for (Artifact d : project.getArtifacts()) {
+            dependencies.put(d.getGroupId() + COLON + d.getArtifactId(), d.getVersion());
+        }
+        return dependencies;
+    }
+
+    private void init() {
+        if (mainSourceLocation == null) {
+            mainSourceLocation = Paths.get(project.getBuild().getSourceDirectory()).toFile();
+        }
+        if (testSourceLocation == null) {
+            testSourceLocation = Paths.get(project.getBuild().getTestSourceDirectory()).toFile();
+        }
+        if (mainResourceLocation == null) {
+            mainResourceLocation = Paths.get(project.getBuild().getResources().get(0).getDirectory()).toFile();
+        }
+        if (testResourceLocation == null) {
+            testResourceLocation = Paths.get(project.getBuild().getTestResources().get(0).getDirectory()).toFile();
+        }
+    }
 }
diff --git a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PreTestCompileHelperMojo.java b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PreTestCompileHelperMojo.java
index e711cb0..a11d796 100644
--- a/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PreTestCompileHelperMojo.java
+++ b/openecomp-be/tools/compile-helper-plugin/src/main/java/org/openecomp/sdc/onboarding/PreTestCompileHelperMojo.java
@@ -17,14 +17,13 @@
 package org.openecomp.sdc.onboarding;
 
 import static org.openecomp.sdc.onboarding.Constants.JACOCO_SKIP;
-import static org.openecomp.sdc.onboarding.Constants.SKIP_TEST_RUN;
 import static org.openecomp.sdc.onboarding.Constants.RESOURCES_CHANGED;
+import static org.openecomp.sdc.onboarding.Constants.SKIP_TESTS;
+import static org.openecomp.sdc.onboarding.Constants.SKIP_TEST_RUN;
 import static org.openecomp.sdc.onboarding.Constants.UNICORN;
 
-import java.io.File;
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.util.stream.Collectors;
+import java.util.List;
+import org.apache.maven.model.Plugin;
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.MojoFailureException;
@@ -33,23 +32,20 @@
 import org.apache.maven.plugins.annotations.Parameter;
 import org.apache.maven.plugins.annotations.ResolutionScope;
 import org.apache.maven.project.MavenProject;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
 
-@Mojo(name = "pre-test-compile-helper", threadSafe = true, defaultPhase = LifecyclePhase.GENERATE_TEST_RESOURCES,
+@Mojo(name = "pre-test-compile-helper", threadSafe = true, defaultPhase = LifecyclePhase.PROCESS_TEST_CLASSES,
         requiresDependencyResolution = ResolutionScope.TEST)
 public class PreTestCompileHelperMojo extends AbstractMojo {
 
     @Parameter
-    private File compiledFilesList;
-    @Parameter
-    private Long staleThreshold;
-    @Parameter
-    private File inputTestFilesList;
-    @Parameter
     private BuildState buildState;
     @Parameter(defaultValue = "${project}", readonly = true)
     private MavenProject project;
     @Parameter(defaultValue = "${project.artifact.groupId}:${project.artifact.artifactId}")
     private String moduleCoordinates;
+    @Parameter(defaultValue = "${project.buildPlugins}", readonly = true)
+    private List<Plugin> plugins;
     @Parameter
     private String excludePackaging;
 
@@ -61,25 +57,17 @@
         if (project.getPackaging().equals(excludePackaging)) {
             return;
         }
-        if (compiledFilesList.exists()
-                    && compiledFilesList.lastModified() > System.currentTimeMillis() - staleThreshold) {
-            try {
-                buildState.markModuleDirty(inputTestFilesList);
-                project.getProperties().setProperty(SKIP_TEST_RUN, Boolean.FALSE.toString());
-            } catch (IOException e) {
-                throw new UncheckedIOException(e);
-            }
+        if (buildState.isTestExecutionMandatory()) {
+            project.getProperties().setProperty(SKIP_TEST_RUN, Boolean.FALSE.toString());
         }
-        boolean isTestMust = buildState.isTestMust(moduleCoordinates,
-                project.getDependencies().stream().map(d -> d.getGroupId() + ":" + d.getArtifactId())
-                       .collect(Collectors.toList()));
+        boolean isTestMust = buildState.isTestMust(moduleCoordinates);
         if (isTestMust) {
             project.getProperties().setProperty(RESOURCES_CHANGED, Boolean.TRUE.toString());
             if (!project.getProperties().containsKey(SKIP_TEST_RUN)) {
                 project.getProperties().setProperty(SKIP_TEST_RUN, Boolean.FALSE.toString());
             }
         }
-        if (!project.getProperties().containsKey(SKIP_TEST_RUN)) {
+        if (!project.getProperties().containsKey(SKIP_TEST_RUN) || isTestSkippedExplicitly()) {
             project.getProperties().setProperty(SKIP_TEST_RUN, Boolean.TRUE.toString());
         }
         if (System.getProperties().containsKey(JACOCO_SKIP) && Boolean.FALSE.equals(Boolean.valueOf(
@@ -87,4 +75,17 @@
             project.getProperties().setProperty(SKIP_TEST_RUN, Boolean.FALSE.toString());
         }
     }
+
+
+    private boolean isTestSkippedExplicitly() {
+        for (Plugin p : plugins) {
+            if ("org.apache.maven.plugins:maven-surefire-plugin".equals(p.getKey())) {
+                Xpp3Dom dom = Xpp3Dom.class.cast(p.getConfiguration());
+                if (dom.getChild(SKIP_TESTS) != null) {
+                    return Boolean.TRUE.equals(Boolean.valueOf(dom.getValue()));
+                }
+            }
+        }
+        return false;
+    }
 }